[Web:Discover] Report events (#20581)

* Define event types

* Define event names for each flow

* Report events upon start, exiting, and next steps

* Update json property name change

* Emit user skipped event

* Emit error events

* Handle unloading event for 'completed' step

* Move updating event state into hook

* Finish emitting events for desktop

* Address CR: rename DiscoverDesktop to DiscoverResources

* Various changes:

- address CR: remove use of ref
- diagnostic traces can also be a success, only emit event on failed traces
- add mysql to discover events
- consistent naming on exit prompt

* Update and add new event names

* Update tests

* Emit events for unimplemented flows (apps and other dbs)

* Redo emitting events for test connection

Send event for EACH test connection failure or success.
If a user does not do any testing, send a skipped event.
This commit is contained in:
Lisa Kim 2023-02-03 11:30:56 -08:00 committed by GitHub
parent b882aee631
commit c7a11477ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 1264 additions and 278 deletions

View file

@ -26,17 +26,24 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type DiscoverResource int32
const (
DiscoverResource_DISCOVER_RESOURCE_UNSPECIFIED DiscoverResource = 0
DiscoverResource_DISCOVER_RESOURCE_SERVER DiscoverResource = 1
DiscoverResource_DISCOVER_RESOURCE_KUBERNETES DiscoverResource = 2
DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED DiscoverResource = 3
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED DiscoverResource = 4
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED DiscoverResource = 5
DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS DiscoverResource = 6
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_RDS DiscoverResource = 7
DiscoverResource_DISCOVER_RESOURCE_APPLICATION_HTTP DiscoverResource = 8
DiscoverResource_DISCOVER_RESOURCE_APPLICATION_TCP DiscoverResource = 9
DiscoverResource_DISCOVER_RESOURCE_WINDOWS_DESKTOP DiscoverResource = 10
DiscoverResource_DISCOVER_RESOURCE_UNSPECIFIED DiscoverResource = 0
DiscoverResource_DISCOVER_RESOURCE_SERVER DiscoverResource = 1
DiscoverResource_DISCOVER_RESOURCE_KUBERNETES DiscoverResource = 2
DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED DiscoverResource = 3
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED DiscoverResource = 4
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED DiscoverResource = 5
DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS DiscoverResource = 6
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_RDS DiscoverResource = 7
DiscoverResource_DISCOVER_RESOURCE_APPLICATION_HTTP DiscoverResource = 8
DiscoverResource_DISCOVER_RESOURCE_APPLICATION_TCP DiscoverResource = 9
DiscoverResource_DISCOVER_RESOURCE_WINDOWS_DESKTOP DiscoverResource = 10
DiscoverResource_DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS DiscoverResource = 11
DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT DiscoverResource = 12
DiscoverResource_DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED DiscoverResource = 13
DiscoverResource_DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED DiscoverResource = 14
DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP DiscoverResource = 15
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_GCP DiscoverResource = 16
DiscoverResource_DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP DiscoverResource = 17
)
var DiscoverResource_name = map[int32]string{
@ -51,20 +58,34 @@ var DiscoverResource_name = map[int32]string{
8: "DISCOVER_RESOURCE_APPLICATION_HTTP",
9: "DISCOVER_RESOURCE_APPLICATION_TCP",
10: "DISCOVER_RESOURCE_WINDOWS_DESKTOP",
11: "DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS",
12: "DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT",
13: "DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED",
14: "DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED",
15: "DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP",
16: "DISCOVER_RESOURCE_DATABASE_MYSQL_GCP",
17: "DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP",
}
var DiscoverResource_value = map[string]int32{
"DISCOVER_RESOURCE_UNSPECIFIED": 0,
"DISCOVER_RESOURCE_SERVER": 1,
"DISCOVER_RESOURCE_KUBERNETES": 2,
"DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED": 3,
"DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED": 4,
"DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED": 5,
"DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS": 6,
"DISCOVER_RESOURCE_DATABASE_MYSQL_RDS": 7,
"DISCOVER_RESOURCE_APPLICATION_HTTP": 8,
"DISCOVER_RESOURCE_APPLICATION_TCP": 9,
"DISCOVER_RESOURCE_WINDOWS_DESKTOP": 10,
"DISCOVER_RESOURCE_UNSPECIFIED": 0,
"DISCOVER_RESOURCE_SERVER": 1,
"DISCOVER_RESOURCE_KUBERNETES": 2,
"DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED": 3,
"DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED": 4,
"DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED": 5,
"DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS": 6,
"DISCOVER_RESOURCE_DATABASE_MYSQL_RDS": 7,
"DISCOVER_RESOURCE_APPLICATION_HTTP": 8,
"DISCOVER_RESOURCE_APPLICATION_TCP": 9,
"DISCOVER_RESOURCE_WINDOWS_DESKTOP": 10,
"DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS": 11,
"DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT": 12,
"DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED": 13,
"DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED": 14,
"DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP": 15,
"DISCOVER_RESOURCE_DATABASE_MYSQL_GCP": 16,
"DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP": 17,
}
func (x DiscoverResource) String() string {
@ -1894,115 +1915,119 @@ func init() {
}
var fileDescriptor_94cf2ca1c69fd564 = []byte{
// 1722 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x99, 0xcf, 0x8f, 0xe3, 0x48,
0x15, 0xc7, 0xed, 0xf4, 0xfc, 0xe8, 0x79, 0xcb, 0xf6, 0x04, 0xb3, 0x3b, 0x93, 0x61, 0xba, 0x7b,
0x7a, 0x32, 0x33, 0x3d, 0xdd, 0x3d, 0x28, 0xa1, 0x77, 0xf9, 0xb1, 0xb0, 0x0b, 0xa3, 0xc4, 0x71,
0xb7, 0xb3, 0xd3, 0xdd, 0x09, 0x65, 0x67, 0x57, 0x70, 0x29, 0xb9, 0xed, 0xea, 0x8c, 0x35, 0x8e,
0x2b, 0xb2, 0xcb, 0xbd, 0x44, 0x08, 0x21, 0x10, 0x42, 0x48, 0x23, 0x21, 0xb8, 0x21, 0x21, 0x71,
0x81, 0x03, 0x07, 0xee, 0x9c, 0xb9, 0x71, 0xe4, 0x1f, 0x40, 0x42, 0xf3, 0x1f, 0x70, 0xe0, 0x00,
0x02, 0x81, 0x52, 0xfe, 0x99, 0x9f, 0x36, 0x23, 0x4e, 0xd9, 0x5b, 0xe2, 0x7a, 0xf5, 0xde, 0xe7,
0xbd, 0x2a, 0xdb, 0xf5, 0x7d, 0x86, 0x7d, 0x46, 0x1c, 0x32, 0xa4, 0x1e, 0xab, 0x07, 0xbe, 0xd1,
0x27, 0xe4, 0x92, 0xb8, 0xcc, 0xaf, 0x5f, 0x1e, 0x66, 0xff, 0xd6, 0x86, 0x1e, 0x65, 0x54, 0xba,
0x1d, 0x9b, 0xd6, 0xb2, 0x63, 0x97, 0x87, 0xd5, 0x03, 0x90, 0x7a, 0xed, 0xa6, 0xe1, 0xba, 0xc4,
0x93, 0x1d, 0xdb, 0x7c, 0xa1, 0x8c, 0x47, 0xa4, 0xb7, 0xe0, 0xaa, 0xe1, 0x10, 0x8f, 0x55, 0xc4,
0x1d, 0x71, 0xef, 0x06, 0x0a, 0xff, 0x54, 0x8f, 0x60, 0xaf, 0xd7, 0xee, 0xb8, 0xe7, 0xd4, 0xf0,
0x2c, 0x99, 0x0e, 0x86, 0x0e, 0x61, 0xe4, 0x98, 0xea, 0xb4, 0x65, 0xf8, 0xcf, 0xc3, 0x8b, 0xa9,
0x87, 0xcf, 0xc3, 0x7a, 0xe0, 0x13, 0xcf, 0x35, 0x06, 0x24, 0x72, 0x92, 0xfc, 0xaf, 0x3e, 0x82,
0x07, 0x89, 0x9f, 0x86, 0x65, 0x1d, 0xd9, 0x9e, 0xcf, 0x10, 0xf1, 0x69, 0xe0, 0x99, 0x24, 0x75,
0x51, 0x3d, 0xc8, 0x84, 0x9b, 0x36, 0x3b, 0x31, 0x58, 0x16, 0xb8, 0xfa, 0x14, 0xee, 0x27, 0xb6,
0x1a, 0x61, 0xb2, 0x47, 0x2c, 0xe2, 0x32, 0xdb, 0x70, 0xb4, 0xe0, 0x7c, 0x60, 0xb3, 0x7c, 0xa6,
0xef, 0xc3, 0xa3, 0xc4, 0x01, 0x22, 0x7d, 0xdb, 0x1f, 0xfb, 0x7f, 0x6e, 0x38, 0x0e, 0x71, 0xfb,
0xa4, 0xa0, 0x13, 0xe9, 0x0e, 0xac, 0x0f, 0x2e, 0x0c, 0xcc, 0x46, 0x43, 0x52, 0x29, 0xf1, 0xb1,
0xeb, 0x83, 0x0b, 0x43, 0x1f, 0x0d, 0x89, 0xb4, 0x05, 0xe0, 0xd0, 0xbe, 0xed, 0xe2, 0x0b, 0x87,
0x7e, 0x52, 0x59, 0xe3, 0x83, 0x37, 0xf8, 0x95, 0x23, 0x87, 0x7e, 0x12, 0xf2, 0x23, 0x62, 0xd2,
0x4b, 0xe2, 0x8d, 0x64, 0x6a, 0x11, 0x5f, 0xa6, 0x2e, 0xb3, 0xdd, 0x80, 0x14, 0xac, 0xe9, 0xfb,
0xb0, 0x35, 0xe3, 0x60, 0x38, 0x2a, 0x38, 0xf9, 0x03, 0xd8, 0x9e, 0x9a, 0xdc, 0xf5, 0x6c, 0x97,
0x15, 0x9c, 0x5d, 0x85, 0x72, 0xcb, 0xf6, 0xf9, 0xe4, 0x53, 0xc2, 0x0c, 0xcb, 0x60, 0x86, 0xb4,
0x01, 0x25, 0xdb, 0x8a, 0x2c, 0x4b, 0xb6, 0x55, 0x35, 0xa0, 0x12, 0xdb, 0xc4, 0x4b, 0x98, 0xd8,
0x2a, 0xb0, 0xee, 0x45, 0xd7, 0xf8, 0x8c, 0x8d, 0x77, 0xf6, 0x6b, 0x0b, 0xb6, 0x6b, 0x6d, 0xda,
0x09, 0x4a, 0xa6, 0x56, 0x5f, 0x80, 0x14, 0x8f, 0x6a, 0x8c, 0x0c, 0x35, 0x66, 0xb0, 0xc0, 0x97,
0x9e, 0xc2, 0x35, 0x9f, 0xff, 0x8a, 0x5c, 0x3f, 0xce, 0x75, 0x1d, 0x4e, 0x44, 0xd1, 0xb4, 0xf1,
0xad, 0x40, 0x3c, 0x8f, 0x7a, 0xd1, 0x82, 0x86, 0x7f, 0xaa, 0xbf, 0x15, 0xe1, 0x56, 0xaf, 0x9d,
0x99, 0xe2, 0x31, 0x62, 0x85, 0xa5, 0x52, 0x60, 0x7d, 0x10, 0xa5, 0xc6, 0x63, 0xbe, 0x51, 0x20,
0x9d, 0xb8, 0x16, 0x28, 0x99, 0x2a, 0xc9, 0x09, 0x78, 0x89, 0x3b, 0x79, 0x52, 0x00, 0x3c, 0xce,
0x3a, 0x86, 0xaf, 0xfe, 0x5b, 0x84, 0x9d, 0x14, 0x33, 0x2e, 0x9a, 0x46, 0x1c, 0x62, 0x32, 0x9b,
0xba, 0xff, 0x57, 0xe0, 0xd3, 0xcc, 0x32, 0x86, 0xc8, 0x87, 0x85, 0x97, 0x31, 0x75, 0x17, 0xbb,
0xc8, 0xe4, 0xbf, 0xf6, 0xfa, 0xf9, 0xff, 0x43, 0x84, 0xcd, 0x34, 0xff, 0x16, 0x19, 0x3a, 0x74,
0xa4, 0x11, 0xef, 0xd2, 0x36, 0xc9, 0xca, 0xe7, 0xfe, 0x2f, 0x11, 0xee, 0x65, 0x72, 0x37, 0x98,
0x71, 0x6e, 0xf8, 0x24, 0x7e, 0xb6, 0xad, 0x7c, 0xfa, 0x3f, 0x2c, 0xc1, 0xc3, 0xd9, 0xf4, 0x65,
0xea, 0x5e, 0xd8, 0xfd, 0xc0, 0x23, 0xa7, 0xfa, 0x89, 0xb6, 0xf2, 0x35, 0xf8, 0x59, 0x09, 0x0e,
0xb3, 0xdb, 0xdf, 0x7f, 0xc1, 0xe8, 0xb0, 0x61, 0x32, 0xfb, 0x92, 0xb4, 0x6c, 0x8f, 0x98, 0x8c,
0x7a, 0x23, 0x9d, 0x52, 0xc7, 0x6f, 0xbb, 0x3e, 0x33, 0x1c, 0x67, 0xe5, 0x0b, 0xf2, 0xb2, 0x04,
0xb5, 0xbc, 0x82, 0x24, 0x5b, 0x64, 0xe5, 0xab, 0xf1, 0xfb, 0x12, 0xec, 0xa6, 0xd5, 0x68, 0x04,
0x8c, 0xc6, 0xbf, 0x89, 0x15, 0xc7, 0xf6, 0x57, 0xbd, 0x0a, 0xd2, 0x63, 0xb8, 0x19, 0x3b, 0xf4,
0xb1, 0x49, 0x03, 0x97, 0x55, 0xae, 0xec, 0x88, 0x7b, 0x6b, 0x68, 0x23, 0xb9, 0x2c, 0x8f, 0xaf,
0x56, 0x7f, 0x52, 0x82, 0xfd, 0x25, 0x4f, 0x94, 0x76, 0xe3, 0xb4, 0x4b, 0x1d, 0xdb, 0x1c, 0xad,
0xfc, 0xbe, 0xf9, 0x8f, 0x08, 0xd5, 0xb4, 0x10, 0xe3, 0xa3, 0xa2, 0x69, 0x0f, 0x0d, 0xc7, 0xff,
0xf4, 0xdc, 0x39, 0xff, 0x14, 0xc7, 0xc7, 0xed, 0xd8, 0x40, 0x27, 0x3e, 0x93, 0xa9, 0xeb, 0x7e,
0x4a, 0x0e, 0x55, 0x7f, 0x17, 0xa1, 0x92, 0x26, 0x1f, 0x0b, 0x41, 0x6b, 0xe5, 0xf3, 0xfe, 0xdb,
0x6d, 0xb8, 0xd9, 0x1b, 0x5b, 0xf3, 0x4c, 0x3b, 0x2e, 0xe9, 0x5c, 0x48, 0x3d, 0xb8, 0x19, 0xd8,
0xf8, 0x9c, 0xeb, 0x67, 0x6c, 0x8e, 0xf5, 0x52, 0x94, 0xf5, 0xe2, 0x08, 0xb3, 0x72, 0x5b, 0x15,
0xd0, 0x9b, 0x81, 0x9d, 0xb9, 0x2a, 0xfd, 0x4a, 0x84, 0xfd, 0xc0, 0xc6, 0x34, 0xd4, 0xa3, 0xd8,
0x8c, 0x6a, 0x8c, 0xfb, 0x14, 0x33, 0x8a, 0xad, 0x58, 0x6f, 0x47, 0x11, 0xc3, 0x9c, 0x1a, 0x4b,
0x22, 0x16, 0x13, 0xed, 0xaa, 0x80, 0x1e, 0x04, 0x76, 0xae, 0xad, 0xf4, 0x52, 0x84, 0x07, 0x19,
0x3a, 0xc3, 0xb2, 0xf0, 0xc5, 0x58, 0x9c, 0xe3, 0xb8, 0xde, 0x11, 0xd7, 0x15, 0xce, 0xf5, 0x41,
0x3e, 0xd7, 0xe2, 0x26, 0x80, 0x2a, 0xa0, 0xed, 0x04, 0x69, 0xae, 0xd9, 0x74, 0xad, 0xe6, 0xd0,
0x38, 0x06, 0x4b, 0x56, 0xe7, 0x6a, 0xd1, 0x5a, 0xe5, 0x74, 0x1c, 0x26, 0x6a, 0xb5, 0xd8, 0x56,
0xfa, 0xb1, 0x08, 0x3b, 0x19, 0x3a, 0x9f, 0x30, 0x6c, 0x26, 0xcd, 0x09, 0xec, 0xf3, 0xc6, 0x42,
0xe5, 0x1a, 0x87, 0xfa, 0x7a, 0x3e, 0xd4, 0xa2, 0xd6, 0x86, 0x2a, 0xa0, 0xcd, 0x84, 0x66, 0x8e,
0x91, 0xf4, 0x73, 0x11, 0x1e, 0x66, 0x30, 0xbc, 0x48, 0x05, 0x60, 0x33, 0x6e, 0x71, 0xc4, 0x28,
0xd7, 0x39, 0xca, 0x37, 0xf3, 0x51, 0x96, 0x35, 0x49, 0x54, 0x01, 0xed, 0x24, 0x38, 0x0b, 0x0c,
0xe3, 0xca, 0x78, 0x51, 0xdb, 0x01, 0x9b, 0xd4, 0xe2, 0x2f, 0xe0, 0xb0, 0xed, 0x11, 0x2d, 0xd7,
0x7a, 0x6e, 0x65, 0x72, 0x9a, 0x26, 0x61, 0x65, 0x16, 0x1b, 0x49, 0xdf, 0x85, 0xcd, 0x79, 0x14,
0xc3, 0x51, 0x44, 0x70, 0x83, 0x13, 0x7c, 0xa5, 0x38, 0x41, 0xb6, 0xeb, 0xa2, 0x0a, 0xa8, 0x32,
0x13, 0x3d, 0x32, 0x90, 0xbe, 0x07, 0x5b, 0xb3, 0x91, 0x87, 0x9e, 0xed, 0xb2, 0x28, 0x34, 0xf0,
0xd0, 0x5f, 0x2d, 0x1a, 0x7a, 0xaa, 0x67, 0xa3, 0x0a, 0xe8, 0xce, 0x54, 0xec, 0xd4, 0x42, 0x72,
0xe0, 0x4e, 0x60, 0x63, 0x2b, 0x7a, 0xda, 0x61, 0x3f, 0xec, 0x60, 0x60, 0xee, 0xbc, 0xf2, 0x06,
0x0f, 0x5c, 0x5f, 0x12, 0x78, 0x5e, 0xe7, 0x43, 0x15, 0xd0, 0xad, 0xc0, 0x9e, 0xdb, 0x13, 0x79,
0x19, 0x6e, 0xbf, 0x24, 0x5c, 0x72, 0x6b, 0xfa, 0x71, 0x2b, 0x22, 0x8a, 0xfc, 0x19, 0x1e, 0xf9,
0x6b, 0x05, 0x22, 0xcf, 0x6f, 0x66, 0x84, 0x3b, 0x2f, 0xa7, 0xe1, 0xf1, 0x03, 0xbe, 0xf1, 0x12,
0x18, 0x8b, 0xb7, 0x05, 0xb0, 0x1f, 0xf6, 0x05, 0x22, 0x90, 0x37, 0x39, 0xc8, 0x97, 0x0b, 0x80,
0xcc, 0x76, 0x15, 0xc2, 0x3d, 0xb7, 0xa4, 0xeb, 0xf0, 0xd3, 0xf0, 0x01, 0x9a, 0x12, 0x44, 0x67,
0xc9, 0xf4, 0xbe, 0x0c, 0x21, 0x36, 0x38, 0xc4, 0x7b, 0x45, 0x20, 0xe6, 0xc9, 0x7b, 0x55, 0x40,
0xf7, 0x32, 0x1c, 0x73, 0x3b, 0x00, 0xbf, 0x0c, 0x9f, 0x9e, 0xb3, 0x28, 0x66, 0x7c, 0x98, 0xc3,
0x03, 0xe6, 0xf8, 0x11, 0xd0, 0x4d, 0x0e, 0xf4, 0x8d, 0xff, 0x01, 0x68, 0x56, 0x70, 0xab, 0x02,
0x7a, 0x38, 0x4b, 0x95, 0xda, 0x31, 0x27, 0xd2, 0x1c, 0x7f, 0x14, 0xe1, 0xbd, 0xc9, 0x75, 0xe2,
0x72, 0x0d, 0x1b, 0x5c, 0xaf, 0x61, 0x2b, 0x16, 0x6c, 0x98, 0x8d, 0x25, 0x2c, 0xb6, 0x43, 0x0d,
0x1b, 0x91, 0x96, 0x39, 0xe9, 0x87, 0x85, 0xd6, 0xaf, 0x90, 0x2c, 0x56, 0x05, 0x74, 0x98, 0x5d,
0xd4, 0x62, 0x5a, 0xfa, 0x0f, 0x22, 0x7c, 0xa9, 0x50, 0x0e, 0x69, 0xb9, 0x43, 0xfe, 0xcf, 0x72,
0xfe, 0xe3, 0xd7, 0xe6, 0x9f, 0x3c, 0x8b, 0xab, 0x02, 0xaa, 0xe5, 0xc1, 0x4f, 0x9d, 0xde, 0x7f,
0x2d, 0xc2, 0x93, 0x2c, 0xb9, 0x11, 0x8c, 0x4f, 0x1e, 0x89, 0x3e, 0xc4, 0xa9, 0x66, 0x0a, 0x81,
0x25, 0x0e, 0xfc, 0xb4, 0x00, 0xf0, 0x32, 0xa1, 0xa9, 0x0a, 0x68, 0x37, 0x05, 0x5d, 0x2a, 0x49,
0x7f, 0x27, 0x42, 0x3d, 0x67, 0xe7, 0xda, 0xc6, 0x00, 0x0f, 0xb9, 0x26, 0x8b, 0x20, 0x3f, 0xc7,
0x21, 0x9b, 0xaf, 0xb3, 0x7f, 0x27, 0xe5, 0x9d, 0x2a, 0xa0, 0xfd, 0x25, 0x9b, 0xb8, 0x6d, 0x0c,
0xb2, 0x5a, 0xf0, 0x17, 0x22, 0xec, 0x66, 0x51, 0x87, 0x89, 0x64, 0x9a, 0x59, 0xf7, 0xb7, 0x38,
0xe1, 0xfb, 0x05, 0x08, 0x17, 0xe9, 0x2e, 0x55, 0x40, 0xd5, 0x14, 0x6d, 0xa1, 0x3a, 0xfb, 0x91,
0x08, 0xf7, 0xb3, 0x4c, 0x8c, 0xf8, 0x6c, 0x4c, 0xe3, 0x4e, 0x3c, 0x8f, 0xdf, 0xce, 0x7d, 0xfb,
0x2d, 0x11, 0x41, 0xaa, 0x80, 0xb6, 0x52, 0x92, 0x79, 0x2a, 0xc9, 0x83, 0xbb, 0x59, 0x86, 0xf8,
0x9c, 0x1b, 0xbf, 0x87, 0x6e, 0xe5, 0x9c, 0xfc, 0x17, 0xa9, 0x90, 0xf0, 0xb5, 0x3b, 0x7f, 0xac,
0x79, 0x1d, 0xae, 0x72, 0x0f, 0x1f, 0x5e, 0x59, 0x2f, 0x95, 0xd7, 0xc6, 0x4f, 0xea, 0xe4, 0x58,
0xd4, 0x27, 0x2c, 0x79, 0x13, 0xf2, 0x57, 0xf0, 0xc1, 0x5f, 0xd6, 0xd2, 0x8f, 0x1b, 0xf1, 0xfe,
0x93, 0xee, 0xc3, 0x56, 0xab, 0xad, 0xc9, 0x9d, 0x8f, 0x14, 0x84, 0x91, 0xa2, 0x75, 0x7a, 0x48,
0x56, 0x70, 0xef, 0x4c, 0xeb, 0x2a, 0x72, 0xfb, 0xa8, 0xad, 0xb4, 0xca, 0x82, 0xb4, 0x09, 0x95,
0x59, 0x13, 0x4d, 0x41, 0x1f, 0x29, 0xa8, 0x2c, 0x4a, 0x3b, 0xb0, 0x39, 0x3b, 0xfa, 0xac, 0xd7,
0x54, 0xd0, 0x99, 0xa2, 0x2b, 0x5a, 0xb9, 0x24, 0xbd, 0x0b, 0xf5, 0x59, 0x8b, 0x56, 0x43, 0x6f,
0x34, 0x1b, 0x9a, 0x82, 0xbb, 0x1d, 0x4d, 0x3f, 0x46, 0x8a, 0x86, 0x35, 0xe5, 0xe4, 0x08, 0xab,
0x1d, 0x4d, 0x57, 0x5a, 0xe5, 0x35, 0xe9, 0x8b, 0xf0, 0x85, 0x25, 0x93, 0x4e, 0xbf, 0xad, 0x7d,
0xeb, 0x64, 0x62, 0xc6, 0x15, 0xe9, 0x1d, 0xa8, 0x2d, 0x9b, 0xd1, 0x39, 0x3b, 0xee, 0xb4, 0x9a,
0x13, 0x73, 0xae, 0x4a, 0x4f, 0xe0, 0x71, 0x11, 0x34, 0xd4, 0xd2, 0xca, 0xd7, 0xa4, 0x3d, 0x78,
0x98, 0x8b, 0x34, 0xb6, 0xbc, 0x2e, 0xed, 0x42, 0x75, 0xd6, 0xb2, 0xd1, 0xed, 0x9e, 0xb4, 0xe5,
0x86, 0xde, 0xee, 0x9c, 0x61, 0x55, 0xd7, 0xbb, 0xe5, 0x75, 0xe9, 0x11, 0xdc, 0x5f, 0x6e, 0xa7,
0xcb, 0xdd, 0xf2, 0x8d, 0xf9, 0x66, 0x1f, 0xb7, 0xcf, 0x5a, 0x9d, 0x8f, 0x35, 0xdc, 0x52, 0xb4,
0x67, 0x7a, 0xa7, 0x5b, 0x86, 0x83, 0xdf, 0x88, 0xb0, 0x31, 0xf9, 0xe1, 0x47, 0xba, 0x07, 0x77,
0x93, 0x99, 0x9a, 0xde, 0xd0, 0x7b, 0xda, 0xd4, 0xda, 0xde, 0x85, 0xdb, 0xd3, 0x06, 0x5a, 0x4f,
0x96, 0x15, 0x4d, 0x2b, 0x8b, 0x73, 0x07, 0x9f, 0xb5, 0xbb, 0x5d, 0xa5, 0x55, 0x2e, 0x49, 0x77,
0xe0, 0xed, 0xe9, 0x41, 0x05, 0xa1, 0x0e, 0x2a, 0xaf, 0xcd, 0x9b, 0xd7, 0x68, 0x76, 0x10, 0x5f,
0xa6, 0x66, 0xe7, 0x4f, 0xaf, 0xb6, 0xc5, 0x3f, 0xbf, 0xda, 0x16, 0xff, 0xfa, 0x6a, 0x5b, 0xfc,
0x4e, 0xa3, 0x6f, 0xb3, 0xe7, 0xc1, 0x79, 0xcd, 0xa4, 0x83, 0x7a, 0xdf, 0x33, 0x2e, 0x6d, 0x66,
0x8c, 0xef, 0x28, 0xc3, 0xa9, 0x27, 0xdf, 0x83, 0x8d, 0xa1, 0x5d, 0xef, 0x13, 0xb7, 0xce, 0x3f,
0xfe, 0xd6, 0xfb, 0x74, 0xea, 0x03, 0xf1, 0xf9, 0x35, 0x3e, 0xf0, 0xee, 0x7f, 0x03, 0x00, 0x00,
0xff, 0xff, 0xf6, 0xfc, 0x2b, 0x45, 0x42, 0x1e, 0x00, 0x00,
// 1784 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x99, 0xcf, 0x6f, 0xe4, 0x48,
0x15, 0xc7, 0xdb, 0x9d, 0x99, 0x4c, 0xe6, 0xcd, 0x4e, 0xe2, 0x2d, 0x76, 0x67, 0x7a, 0x98, 0x24,
0x93, 0xe9, 0xf9, 0x95, 0x64, 0x56, 0xe9, 0xcd, 0xee, 0x02, 0x0b, 0xbb, 0x30, 0xea, 0xb8, 0x9d,
0xb8, 0x77, 0x92, 0x74, 0x6f, 0xd9, 0xbd, 0x2b, 0xb8, 0x94, 0x1c, 0xbb, 0xd2, 0x63, 0x8d, 0xdb,
0x6e, 0xd9, 0xe5, 0x2c, 0x11, 0x42, 0x08, 0x84, 0x10, 0xd2, 0x48, 0x08, 0x6e, 0x48, 0x48, 0x5c,
0xe0, 0x80, 0x10, 0x77, 0xce, 0xdc, 0x38, 0xf2, 0x27, 0xa0, 0xf9, 0x0f, 0x38, 0x70, 0x00, 0x81,
0x40, 0x2e, 0xff, 0xec, 0x9f, 0x36, 0x23, 0x4e, 0x99, 0x5b, 0xb7, 0xeb, 0xd5, 0x7b, 0x9f, 0xf7,
0xaa, 0x6c, 0xd7, 0xf7, 0x19, 0xb6, 0x18, 0xb5, 0xe9, 0xd0, 0xf5, 0x58, 0x23, 0xf0, 0xf5, 0x3e,
0xa5, 0x67, 0xd4, 0x61, 0x7e, 0xe3, 0x6c, 0x37, 0xff, 0x77, 0x67, 0xe8, 0xb9, 0xcc, 0x45, 0x37,
0x13, 0xd3, 0x9d, 0xfc, 0xd8, 0xd9, 0x6e, 0x7d, 0x1b, 0x50, 0xaf, 0xbd, 0xa7, 0x3b, 0x0e, 0xf5,
0x24, 0xdb, 0x32, 0x9e, 0xcb, 0xe1, 0x08, 0x7a, 0x0b, 0x2e, 0xeb, 0x36, 0xf5, 0x58, 0x4d, 0xd8,
0x10, 0x36, 0xaf, 0xe2, 0xe8, 0x4f, 0x7d, 0x1f, 0x36, 0x7b, 0xed, 0x8e, 0x73, 0xe2, 0xea, 0x9e,
0x29, 0xb9, 0x83, 0xa1, 0x4d, 0x19, 0x3d, 0x70, 0x35, 0xb7, 0xa5, 0xfb, 0xcf, 0xa2, 0x8b, 0x99,
0x87, 0x2f, 0xc3, 0x52, 0xe0, 0x53, 0xcf, 0xd1, 0x07, 0x34, 0x76, 0x92, 0xfe, 0xaf, 0x3f, 0x80,
0x7b, 0xa9, 0x9f, 0xa6, 0x69, 0xee, 0x5b, 0x9e, 0xcf, 0x30, 0xf5, 0xdd, 0xc0, 0x33, 0x68, 0xe6,
0xa2, 0xbe, 0x9d, 0x0b, 0x37, 0x6e, 0x76, 0xa8, 0xb3, 0x3c, 0x70, 0xfd, 0x09, 0xdc, 0x4d, 0x6d,
0x55, 0xca, 0x24, 0x8f, 0x9a, 0xd4, 0x61, 0x96, 0x6e, 0xab, 0xc1, 0xc9, 0xc0, 0x62, 0xc5, 0x4c,
0xdf, 0x87, 0x07, 0xa9, 0x03, 0x4c, 0xfb, 0x96, 0x1f, 0xfa, 0x7f, 0xa6, 0xdb, 0x36, 0x75, 0xfa,
0xb4, 0xa4, 0x13, 0x74, 0x0b, 0x96, 0x06, 0xa7, 0x3a, 0x61, 0xe7, 0x43, 0x5a, 0xab, 0xf2, 0xb1,
0x2b, 0x83, 0x53, 0x5d, 0x3b, 0x1f, 0x52, 0xb4, 0x06, 0x60, 0xbb, 0x7d, 0xcb, 0x21, 0xa7, 0xb6,
0xfb, 0x45, 0x6d, 0x81, 0x0f, 0x5e, 0xe5, 0x57, 0xf6, 0x6d, 0xf7, 0x8b, 0x88, 0x1f, 0x53, 0xc3,
0x3d, 0xa3, 0xde, 0xb9, 0xe4, 0x9a, 0xd4, 0x97, 0x5c, 0x87, 0x59, 0x4e, 0x40, 0x4b, 0xd6, 0xf4,
0x23, 0x58, 0x9b, 0x70, 0x30, 0x3c, 0x2f, 0x39, 0xf9, 0x63, 0x58, 0x1f, 0x9b, 0xdc, 0xf5, 0x2c,
0x87, 0x95, 0x9c, 0x5d, 0x07, 0xb1, 0x65, 0xf9, 0x7c, 0xf2, 0x11, 0x65, 0xba, 0xa9, 0x33, 0x1d,
0x2d, 0x43, 0xd5, 0x32, 0x63, 0xcb, 0xaa, 0x65, 0xd6, 0x75, 0xa8, 0x25, 0x36, 0xc9, 0x12, 0xa6,
0xb6, 0x32, 0x2c, 0x79, 0xf1, 0x35, 0x3e, 0x63, 0xf9, 0xbd, 0xad, 0x9d, 0x19, 0xdb, 0x75, 0x67,
0xdc, 0x09, 0x4e, 0xa7, 0xd6, 0x9f, 0x03, 0x4a, 0x46, 0x55, 0x46, 0x87, 0x2a, 0xd3, 0x59, 0xe0,
0xa3, 0x27, 0xb0, 0xe8, 0xf3, 0x5f, 0xb1, 0xeb, 0x47, 0x85, 0xae, 0xa3, 0x89, 0x38, 0x9e, 0x16,
0xde, 0x0a, 0xd4, 0xf3, 0x5c, 0x2f, 0x5e, 0xd0, 0xe8, 0x4f, 0xfd, 0xb7, 0x02, 0xdc, 0xe8, 0xb5,
0x73, 0x53, 0x3c, 0x46, 0xcd, 0xa8, 0x54, 0x32, 0x2c, 0x0d, 0xe2, 0xd4, 0x78, 0xcc, 0x6b, 0x25,
0xd2, 0x49, 0x6a, 0x81, 0xd3, 0xa9, 0x48, 0x4a, 0xc1, 0xab, 0xdc, 0xc9, 0xe3, 0x12, 0xe0, 0x49,
0xd6, 0x09, 0x7c, 0xfd, 0xdf, 0x02, 0x6c, 0x64, 0x98, 0x49, 0xd1, 0x54, 0x6a, 0x53, 0x83, 0x59,
0xae, 0xf3, 0x7f, 0x05, 0x3e, 0xca, 0x2d, 0x63, 0x84, 0xbc, 0x5b, 0x7a, 0x19, 0x33, 0x77, 0x89,
0x8b, 0x5c, 0xfe, 0x0b, 0xaf, 0x9e, 0xff, 0x3f, 0x04, 0x58, 0xcd, 0xf2, 0x6f, 0xd1, 0xa1, 0xed,
0x9e, 0xab, 0xd4, 0x3b, 0xb3, 0x0c, 0x7a, 0xe1, 0x73, 0xff, 0x97, 0x00, 0x77, 0x72, 0xb9, 0xeb,
0x4c, 0x3f, 0xd1, 0x7d, 0x9a, 0x3c, 0xdb, 0x2e, 0x7c, 0xfa, 0x3f, 0xac, 0xc2, 0xfd, 0xc9, 0xf4,
0x25, 0xd7, 0x39, 0xb5, 0xfa, 0x81, 0x47, 0x8f, 0xb4, 0x43, 0xf5, 0xc2, 0xd7, 0xe0, 0x67, 0x55,
0xd8, 0xcd, 0x6f, 0x7f, 0xff, 0x39, 0x73, 0x87, 0x4d, 0x83, 0x59, 0x67, 0xb4, 0x65, 0x79, 0xd4,
0x60, 0xae, 0x77, 0xae, 0xb9, 0xae, 0xed, 0xb7, 0x1d, 0x9f, 0xe9, 0xb6, 0x7d, 0xe1, 0x0b, 0xf2,
0xa2, 0x0a, 0x3b, 0x45, 0x05, 0x49, 0xb7, 0xc8, 0x85, 0xaf, 0xc6, 0x1f, 0xaa, 0xf0, 0x30, 0xab,
0x46, 0x33, 0x60, 0x6e, 0xf2, 0x9b, 0x9a, 0x49, 0x6c, 0xff, 0xa2, 0x57, 0x01, 0x3d, 0x82, 0x95,
0xc4, 0xa1, 0x4f, 0x0c, 0x37, 0x70, 0x58, 0xed, 0xd2, 0x86, 0xb0, 0xb9, 0x80, 0x97, 0xd3, 0xcb,
0x52, 0x78, 0xb5, 0xfe, 0x93, 0x2a, 0x6c, 0xcd, 0x79, 0xa2, 0xb4, 0x9b, 0x47, 0x5d, 0xd7, 0xb6,
0x8c, 0xf3, 0x0b, 0xbf, 0x6f, 0xfe, 0x23, 0x40, 0x3d, 0x2b, 0x44, 0x78, 0x54, 0x34, 0xac, 0xa1,
0x6e, 0xfb, 0xaf, 0xcf, 0x9d, 0xf3, 0x4f, 0x21, 0x3c, 0x6e, 0x27, 0x06, 0x1a, 0xf5, 0x99, 0xe4,
0x3a, 0xce, 0x6b, 0x72, 0xa8, 0xfa, 0xbb, 0x00, 0xb5, 0x2c, 0xf9, 0x44, 0x08, 0x9a, 0x17, 0x3e,
0xef, 0xbf, 0xdd, 0x84, 0x95, 0x5e, 0x68, 0xcd, 0x33, 0xed, 0x38, 0xb4, 0x73, 0x8a, 0x7a, 0xb0,
0x12, 0x58, 0xe4, 0x84, 0xeb, 0x67, 0x62, 0x84, 0x7a, 0x29, 0xce, 0x7a, 0x76, 0x84, 0x49, 0xb9,
0xad, 0x54, 0xf0, 0xf5, 0xc0, 0xca, 0x5d, 0x45, 0xbf, 0x12, 0x60, 0x2b, 0xb0, 0x88, 0x1b, 0xe9,
0x51, 0x62, 0xc4, 0x35, 0x26, 0x7d, 0x97, 0x30, 0x97, 0x98, 0x89, 0xde, 0x8e, 0x23, 0x46, 0x39,
0x35, 0xe7, 0x44, 0x2c, 0x27, 0xda, 0x95, 0x0a, 0xbe, 0x17, 0x58, 0x85, 0xb6, 0xe8, 0x85, 0x00,
0xf7, 0x72, 0x74, 0xba, 0x69, 0x92, 0xd3, 0x50, 0x9c, 0x93, 0xa4, 0xde, 0x31, 0xd7, 0x25, 0xce,
0xf5, 0x71, 0x31, 0xd7, 0xec, 0x26, 0x80, 0x52, 0xc1, 0xeb, 0x29, 0xd2, 0x54, 0xb3, 0xf1, 0x5a,
0x4d, 0xa1, 0xb1, 0x75, 0x96, 0xae, 0xce, 0xe5, 0xb2, 0xb5, 0x2a, 0xe8, 0x38, 0x8c, 0xd4, 0x6a,
0xb6, 0x2d, 0xfa, 0xb1, 0x00, 0x1b, 0x39, 0x3a, 0x9f, 0x32, 0x62, 0xa4, 0xcd, 0x09, 0xe2, 0xf3,
0xc6, 0x42, 0x6d, 0x91, 0x43, 0x7d, 0xa3, 0x18, 0x6a, 0x56, 0x6b, 0x43, 0xa9, 0xe0, 0xd5, 0x94,
0x66, 0x8a, 0x11, 0xfa, 0xb9, 0x00, 0xf7, 0x73, 0x18, 0x5e, 0xac, 0x02, 0x88, 0x91, 0xb4, 0x38,
0x12, 0x94, 0x2b, 0x1c, 0xe5, 0x5b, 0xc5, 0x28, 0xf3, 0x9a, 0x24, 0x4a, 0x05, 0x6f, 0xa4, 0x38,
0x33, 0x0c, 0x93, 0xca, 0x78, 0x71, 0xdb, 0x81, 0x18, 0xae, 0xc9, 0x5f, 0xc0, 0x51, 0xdb, 0x23,
0x5e, 0xae, 0xa5, 0xc2, 0xca, 0x14, 0x34, 0x4d, 0xa2, 0xca, 0xcc, 0x36, 0x42, 0xdf, 0x85, 0xd5,
0x69, 0x14, 0xc3, 0xf3, 0x98, 0xe0, 0x2a, 0x27, 0xf8, 0x6a, 0x79, 0x82, 0x7c, 0xd7, 0x45, 0xa9,
0xe0, 0xda, 0x44, 0xf4, 0xd8, 0x00, 0x7d, 0x0f, 0xd6, 0x26, 0x23, 0x0f, 0x3d, 0xcb, 0x61, 0x71,
0x68, 0xe0, 0xa1, 0xbf, 0x56, 0x36, 0xf4, 0x58, 0xcf, 0x46, 0xa9, 0xe0, 0x5b, 0x63, 0xb1, 0x33,
0x0b, 0x64, 0xc3, 0xad, 0xc0, 0x22, 0x66, 0xfc, 0xb4, 0x23, 0x7e, 0xd4, 0xc1, 0x20, 0xdc, 0x79,
0xed, 0x1a, 0x0f, 0xdc, 0x98, 0x13, 0x78, 0x5a, 0xe7, 0x43, 0xa9, 0xe0, 0x1b, 0x81, 0x35, 0xb5,
0x27, 0xf2, 0x22, 0xda, 0x7e, 0x69, 0xb8, 0xf4, 0xd6, 0xf4, 0x93, 0x56, 0x44, 0x1c, 0xf9, 0x0d,
0x1e, 0xf9, 0xeb, 0x25, 0x22, 0x4f, 0x6f, 0x66, 0x44, 0x3b, 0xaf, 0xa0, 0xe1, 0xf1, 0x03, 0xbe,
0xf1, 0x52, 0x18, 0x93, 0xb7, 0x05, 0x88, 0x1f, 0xf5, 0x05, 0x62, 0x90, 0xeb, 0x1c, 0xe4, 0x2b,
0x25, 0x40, 0x26, 0xbb, 0x0a, 0xd1, 0x9e, 0x9b, 0xd3, 0x75, 0xf8, 0x69, 0xf4, 0x00, 0xcd, 0x08,
0xe2, 0xb3, 0x64, 0x76, 0x5f, 0x46, 0x10, 0xcb, 0x1c, 0xe2, 0xc3, 0x32, 0x10, 0xd3, 0xe4, 0xbd,
0x52, 0xc1, 0x77, 0x72, 0x1c, 0x53, 0x3b, 0x00, 0xbf, 0x8c, 0x9e, 0x9e, 0x93, 0x28, 0x46, 0x72,
0x98, 0x23, 0x03, 0x66, 0xfb, 0x31, 0xd0, 0x0a, 0x07, 0xfa, 0xe6, 0xff, 0x00, 0x34, 0x29, 0xb8,
0x95, 0x0a, 0xbe, 0x3f, 0x49, 0x95, 0xd9, 0x31, 0x3b, 0xd6, 0x1c, 0x7f, 0x12, 0xe0, 0xc3, 0xd1,
0x75, 0xe2, 0x72, 0x8d, 0xe8, 0x5c, 0xaf, 0x11, 0x33, 0x11, 0x6c, 0x84, 0x85, 0x12, 0x96, 0x58,
0x91, 0x86, 0x8d, 0x49, 0x45, 0x4e, 0xfa, 0x49, 0xa9, 0xf5, 0x2b, 0x25, 0x8b, 0x95, 0x0a, 0xde,
0xcd, 0x2f, 0x6a, 0x39, 0x2d, 0xfd, 0x47, 0x01, 0x3e, 0x28, 0x95, 0x43, 0x56, 0xee, 0x88, 0xff,
0x4d, 0xce, 0x7f, 0xf0, 0xca, 0xfc, 0xa3, 0x67, 0x71, 0xa5, 0x82, 0x77, 0x8a, 0xe0, 0xc7, 0x4e,
0xef, 0xbf, 0x16, 0xe0, 0x71, 0x9e, 0x5c, 0x0f, 0xc2, 0x93, 0x47, 0xaa, 0x0f, 0x49, 0xa6, 0x99,
0x22, 0x60, 0xc4, 0x81, 0x9f, 0x94, 0x00, 0x9e, 0x27, 0x34, 0x95, 0x0a, 0x7e, 0x98, 0x81, 0xce,
0x95, 0xa4, 0xbf, 0x13, 0xa0, 0x51, 0xb0, 0x73, 0x2d, 0x7d, 0x40, 0x86, 0x5c, 0x93, 0xc5, 0x90,
0x5f, 0xe2, 0x90, 0x7b, 0xaf, 0xb2, 0x7f, 0x47, 0xe5, 0x9d, 0x52, 0xc1, 0x5b, 0x73, 0x36, 0x71,
0x5b, 0x1f, 0xe4, 0xb5, 0xe0, 0x2f, 0x04, 0x78, 0x98, 0x47, 0x1d, 0xa6, 0x92, 0x69, 0x62, 0xdd,
0xdf, 0xe2, 0x84, 0x1f, 0x95, 0x20, 0x9c, 0xa5, 0xbb, 0x94, 0x0a, 0xae, 0x67, 0x68, 0x33, 0xd5,
0xd9, 0x8f, 0x04, 0xb8, 0x9b, 0x67, 0x62, 0xd4, 0x67, 0x21, 0x8d, 0x33, 0xf2, 0x3c, 0x7e, 0xbb,
0xf0, 0xed, 0x37, 0x47, 0x04, 0x29, 0x15, 0xbc, 0x96, 0x91, 0x4c, 0x53, 0x49, 0x1e, 0xdc, 0xce,
0x33, 0x24, 0xe7, 0xdc, 0xe4, 0x3d, 0x74, 0xa3, 0xe0, 0xe4, 0x3f, 0x4b, 0x85, 0x44, 0xaf, 0xdd,
0xe9, 0x63, 0x7b, 0x57, 0xe0, 0x32, 0xf7, 0xf0, 0xc9, 0xa5, 0xa5, 0xaa, 0xb8, 0x10, 0x3e, 0xa9,
0xd3, 0x63, 0x51, 0x9f, 0xb2, 0xf4, 0x4d, 0xc8, 0x5f, 0xc1, 0xdb, 0xbf, 0x5f, 0xcc, 0x3e, 0x6e,
0x24, 0xfb, 0x0f, 0xdd, 0x85, 0xb5, 0x56, 0x5b, 0x95, 0x3a, 0x9f, 0xc9, 0x98, 0x60, 0x59, 0xed,
0xf4, 0xb0, 0x24, 0x93, 0xde, 0xb1, 0xda, 0x95, 0xa5, 0xf6, 0x7e, 0x5b, 0x6e, 0x89, 0x15, 0xb4,
0x0a, 0xb5, 0x49, 0x13, 0x55, 0xc6, 0x9f, 0xc9, 0x58, 0x14, 0xd0, 0x06, 0xac, 0x4e, 0x8e, 0x3e,
0xed, 0xed, 0xc9, 0xf8, 0x58, 0xd6, 0x64, 0x55, 0xac, 0xa2, 0xf7, 0xa1, 0x31, 0x69, 0xd1, 0x6a,
0x6a, 0xcd, 0xbd, 0xa6, 0x2a, 0x93, 0x6e, 0x47, 0xd5, 0x0e, 0xb0, 0xac, 0x12, 0x55, 0x3e, 0xdc,
0x27, 0x4a, 0x47, 0xd5, 0xe4, 0x96, 0xb8, 0x80, 0xde, 0x85, 0x77, 0xe6, 0x4c, 0x3a, 0xfa, 0xb6,
0xfa, 0xe9, 0xe1, 0xc8, 0x8c, 0x4b, 0xe8, 0x3d, 0xd8, 0x99, 0x37, 0xa3, 0x73, 0x7c, 0xd0, 0x69,
0xed, 0x8d, 0xcc, 0xb9, 0x8c, 0x1e, 0xc3, 0xa3, 0x32, 0x68, 0xb8, 0xa5, 0x8a, 0x8b, 0x68, 0x13,
0xee, 0x17, 0x22, 0x85, 0x96, 0x57, 0xd0, 0x43, 0xa8, 0x4f, 0x5a, 0x36, 0xbb, 0xdd, 0xc3, 0xb6,
0xd4, 0xd4, 0xda, 0x9d, 0x63, 0xa2, 0x68, 0x5a, 0x57, 0x5c, 0x42, 0x0f, 0xe0, 0xee, 0x7c, 0x3b,
0x4d, 0xea, 0x8a, 0x57, 0xa7, 0x9b, 0x7d, 0xde, 0x3e, 0x6e, 0x75, 0x3e, 0x57, 0x49, 0x4b, 0x56,
0x9f, 0x6a, 0x9d, 0xae, 0x08, 0xe8, 0x1d, 0xd8, 0x9c, 0xc3, 0xa7, 0x7e, 0x7a, 0x18, 0xad, 0x19,
0x67, 0xbc, 0x56, 0x50, 0xe0, 0x2c, 0x75, 0xb9, 0xa5, 0x2a, 0xed, 0x7d, 0x4d, 0x7c, 0x03, 0x7d,
0x00, 0xef, 0x96, 0xf2, 0x9f, 0x2f, 0xf1, 0xf5, 0x82, 0x38, 0x58, 0x6e, 0xb5, 0x47, 0x97, 0x7e,
0xb9, 0xec, 0xa2, 0x1c, 0x48, 0x5d, 0x71, 0xa5, 0xd4, 0xa2, 0x84, 0x96, 0x62, 0xe9, 0xf2, 0x84,
0xd6, 0x6f, 0x6e, 0xff, 0x46, 0x80, 0xe5, 0xd1, 0xaf, 0x68, 0xe8, 0x0e, 0xdc, 0x4e, 0x1d, 0xa8,
0x5a, 0x53, 0xeb, 0xa9, 0x63, 0x37, 0xca, 0x6d, 0xb8, 0x39, 0x6e, 0xa0, 0xf6, 0x24, 0x49, 0x56,
0x55, 0x51, 0x98, 0x3a, 0xf8, 0xb4, 0xdd, 0xed, 0xca, 0x2d, 0xb1, 0x8a, 0x6e, 0xc1, 0xdb, 0xe3,
0x83, 0x32, 0xc6, 0x1d, 0x2c, 0x2e, 0x4c, 0x9b, 0xd7, 0xdc, 0xeb, 0x60, 0xbe, 0xe7, 0xf7, 0x3a,
0x7f, 0x7e, 0xb9, 0x2e, 0xfc, 0xe5, 0xe5, 0xba, 0xf0, 0xd7, 0x97, 0xeb, 0xc2, 0x77, 0x9a, 0x7d,
0x8b, 0x3d, 0x0b, 0x4e, 0x76, 0x0c, 0x77, 0xd0, 0xe8, 0x7b, 0xfa, 0x99, 0xc5, 0xf4, 0xf0, 0xf1,
0xa4, 0xdb, 0x8d, 0xf4, 0xe3, 0xba, 0x3e, 0xb4, 0x1a, 0x7d, 0xea, 0x34, 0xf8, 0x97, 0xf4, 0x46,
0xdf, 0x1d, 0xfb, 0xda, 0x7e, 0xb2, 0xc8, 0x07, 0xde, 0xff, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0x2e, 0xf2, 0x3e, 0x8f, 0x1f, 0x00, 0x00,
}
func (m *UIBannerClickEvent) Marshal() (dAtA []byte, err error) {

View file

@ -99,6 +99,13 @@ enum DiscoverResource {
DISCOVER_RESOURCE_APPLICATION_HTTP = 8;
DISCOVER_RESOURCE_APPLICATION_TCP = 9;
DISCOVER_RESOURCE_WINDOWS_DESKTOP = 10;
DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS = 11;
DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT = 12;
DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED = 13;
DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED = 14;
DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP = 15;
DISCOVER_RESOURCE_DATABASE_MYSQL_GCP = 16;
DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP = 17;
}
// DiscoverResourceMetadata contains common metadata identifying resource type being added.

View file

@ -40,17 +40,24 @@ const (
type DiscoverResource int32
const (
DiscoverResource_DISCOVER_RESOURCE_UNSPECIFIED DiscoverResource = 0
DiscoverResource_DISCOVER_RESOURCE_SERVER DiscoverResource = 1
DiscoverResource_DISCOVER_RESOURCE_KUBERNETES DiscoverResource = 2
DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED DiscoverResource = 3
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED DiscoverResource = 4
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED DiscoverResource = 5
DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS DiscoverResource = 6
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_RDS DiscoverResource = 7
DiscoverResource_DISCOVER_RESOURCE_APPLICATION_HTTP DiscoverResource = 8
DiscoverResource_DISCOVER_RESOURCE_APPLICATION_TCP DiscoverResource = 9
DiscoverResource_DISCOVER_RESOURCE_WINDOWS_DESKTOP DiscoverResource = 10
DiscoverResource_DISCOVER_RESOURCE_UNSPECIFIED DiscoverResource = 0
DiscoverResource_DISCOVER_RESOURCE_SERVER DiscoverResource = 1
DiscoverResource_DISCOVER_RESOURCE_KUBERNETES DiscoverResource = 2
DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED DiscoverResource = 3
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED DiscoverResource = 4
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED DiscoverResource = 5
DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS DiscoverResource = 6
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_RDS DiscoverResource = 7
DiscoverResource_DISCOVER_RESOURCE_APPLICATION_HTTP DiscoverResource = 8
DiscoverResource_DISCOVER_RESOURCE_APPLICATION_TCP DiscoverResource = 9
DiscoverResource_DISCOVER_RESOURCE_WINDOWS_DESKTOP DiscoverResource = 10
DiscoverResource_DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS DiscoverResource = 11
DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT DiscoverResource = 12
DiscoverResource_DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED DiscoverResource = 13
DiscoverResource_DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED DiscoverResource = 14
DiscoverResource_DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP DiscoverResource = 15
DiscoverResource_DISCOVER_RESOURCE_DATABASE_MYSQL_GCP DiscoverResource = 16
DiscoverResource_DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP DiscoverResource = 17
)
// Enum value maps for DiscoverResource.
@ -67,19 +74,33 @@ var (
8: "DISCOVER_RESOURCE_APPLICATION_HTTP",
9: "DISCOVER_RESOURCE_APPLICATION_TCP",
10: "DISCOVER_RESOURCE_WINDOWS_DESKTOP",
11: "DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS",
12: "DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT",
13: "DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED",
14: "DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED",
15: "DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP",
16: "DISCOVER_RESOURCE_DATABASE_MYSQL_GCP",
17: "DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP",
}
DiscoverResource_value = map[string]int32{
"DISCOVER_RESOURCE_UNSPECIFIED": 0,
"DISCOVER_RESOURCE_SERVER": 1,
"DISCOVER_RESOURCE_KUBERNETES": 2,
"DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED": 3,
"DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED": 4,
"DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED": 5,
"DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS": 6,
"DISCOVER_RESOURCE_DATABASE_MYSQL_RDS": 7,
"DISCOVER_RESOURCE_APPLICATION_HTTP": 8,
"DISCOVER_RESOURCE_APPLICATION_TCP": 9,
"DISCOVER_RESOURCE_WINDOWS_DESKTOP": 10,
"DISCOVER_RESOURCE_UNSPECIFIED": 0,
"DISCOVER_RESOURCE_SERVER": 1,
"DISCOVER_RESOURCE_KUBERNETES": 2,
"DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED": 3,
"DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED": 4,
"DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED": 5,
"DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS": 6,
"DISCOVER_RESOURCE_DATABASE_MYSQL_RDS": 7,
"DISCOVER_RESOURCE_APPLICATION_HTTP": 8,
"DISCOVER_RESOURCE_APPLICATION_TCP": 9,
"DISCOVER_RESOURCE_WINDOWS_DESKTOP": 10,
"DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS": 11,
"DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT": 12,
"DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED": 13,
"DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED": 14,
"DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP": 15,
"DISCOVER_RESOURCE_DATABASE_MYSQL_GCP": 16,
"DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP": 17,
}
)
@ -2953,7 +2974,7 @@ var file_prehog_v1alpha_teleport_proto_rawDesc = []byte{
0x73, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70,
0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x17, 0x0a, 0x15, 0x48, 0x65,
0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x2a, 0xdd, 0x03, 0x0a, 0x10, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72,
0x6e, 0x73, 0x65, 0x2a, 0xaa, 0x06, 0x0a, 0x10, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72,
0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x49, 0x53, 0x43,
0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x55, 0x4e,
0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x44,
@ -2983,35 +3004,56 @@ var file_prehog_v1alpha_teleport_proto_rawDesc = []byte{
0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x09, 0x12, 0x25, 0x0a, 0x21,
0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43,
0x45, 0x5f, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, 0x53, 0x5f, 0x44, 0x45, 0x53, 0x4b, 0x54, 0x4f,
0x50, 0x10, 0x0a, 0x2a, 0xa3, 0x01, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72,
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56,
0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x43, 0x4f,
0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45,
0x53, 0x53, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52,
0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x4b, 0x49, 0x50, 0x50, 0x45, 0x44, 0x10,
0x02, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54,
0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17,
0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f,
0x41, 0x42, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x04, 0x32, 0xd4, 0x01, 0x0a, 0x18, 0x54, 0x65,
0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53,
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x58, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74,
0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x65, 0x68,
0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69,
0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
0x12, 0x5e, 0x0a, 0x0d, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72,
0x74, 0x12, 0x24, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65,
0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
0x42, 0x3f, 0x5a, 0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67,
0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c,
0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
0x67, 0x6f, 0x2f, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x50, 0x10, 0x0a, 0x12, 0x2c, 0x0a, 0x28, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f,
0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53,
0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x44, 0x53, 0x10,
0x0b, 0x12, 0x30, 0x0a, 0x2c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45,
0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f,
0x50, 0x4f, 0x53, 0x54, 0x47, 0x52, 0x45, 0x53, 0x5f, 0x52, 0x45, 0x44, 0x53, 0x48, 0x49, 0x46,
0x54, 0x10, 0x0c, 0x12, 0x34, 0x0a, 0x30, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f,
0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53,
0x45, 0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x45, 0x4c, 0x46,
0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x0d, 0x12, 0x30, 0x0a, 0x2c, 0x44, 0x49, 0x53,
0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44,
0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x52, 0x45, 0x44, 0x49, 0x53, 0x5f, 0x53, 0x45,
0x4c, 0x46, 0x5f, 0x48, 0x4f, 0x53, 0x54, 0x45, 0x44, 0x10, 0x0e, 0x12, 0x2b, 0x0a, 0x27, 0x44,
0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45,
0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x50, 0x4f, 0x53, 0x54, 0x47, 0x52,
0x45, 0x53, 0x5f, 0x47, 0x43, 0x50, 0x10, 0x0f, 0x12, 0x28, 0x0a, 0x24, 0x44, 0x49, 0x53, 0x43,
0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41,
0x54, 0x41, 0x42, 0x41, 0x53, 0x45, 0x5f, 0x4d, 0x59, 0x53, 0x51, 0x4c, 0x5f, 0x47, 0x43, 0x50,
0x10, 0x10, 0x12, 0x2c, 0x0a, 0x28, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x52,
0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x42, 0x41, 0x53, 0x45,
0x5f, 0x53, 0x51, 0x4c, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x5f, 0x47, 0x43, 0x50, 0x10, 0x11,
0x2a, 0xa3, 0x01, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61,
0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f,
0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52,
0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x10,
0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54,
0x41, 0x54, 0x55, 0x53, 0x5f, 0x53, 0x4b, 0x49, 0x50, 0x50, 0x45, 0x44, 0x10, 0x02, 0x12, 0x19,
0x0a, 0x15, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55,
0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53,
0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x42, 0x4f,
0x52, 0x54, 0x45, 0x44, 0x10, 0x04, 0x32, 0xd4, 0x01, 0x0a, 0x18, 0x54, 0x65, 0x6c, 0x65, 0x70,
0x6f, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x12, 0x58, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76,
0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a,
0x0d, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x24,
0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e,
0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70,
0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x3f, 0x5a,
0x3d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76,
0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f,
0x72, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f,
0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View file

@ -1215,6 +1215,13 @@ export enum DiscoverResource {
DISCOVER_RESOURCE_APPLICATION_HTTP = 8,
DISCOVER_RESOURCE_APPLICATION_TCP = 9,
DISCOVER_RESOURCE_WINDOWS_DESKTOP = 10,
DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS = 11,
DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT = 12,
DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED = 13,
DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED = 14,
DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP = 15,
DISCOVER_RESOURCE_DATABASE_MYSQL_GCP = 16,
DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP = 17,
}
export enum DiscoverStatus {

View file

@ -8310,7 +8310,14 @@ proto.prehog.v1alpha.DiscoverResource = {
DISCOVER_RESOURCE_DATABASE_MYSQL_RDS: 7,
DISCOVER_RESOURCE_APPLICATION_HTTP: 8,
DISCOVER_RESOURCE_APPLICATION_TCP: 9,
DISCOVER_RESOURCE_WINDOWS_DESKTOP: 10
DISCOVER_RESOURCE_WINDOWS_DESKTOP: 10,
DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS: 11,
DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT: 12,
DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED: 13,
DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED: 14,
DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP: 15,
DISCOVER_RESOURCE_DATABASE_MYSQL_GCP: 16,
DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP: 17
};
/**

View file

@ -228,7 +228,17 @@ func convertUserEventRequestToUsageEvent(req createUserEventRequest) (*v1.UsageE
nil
case uiDiscoverStartedEvent,
uiDiscoverResourceSelectionEvent:
uiDiscoverResourceSelectionEvent,
uiDiscoverDeployServiceEvent,
uiDiscoverDatabaseRegisterEvent,
uiDiscoverDatabaseConfigureMTLSEvent,
uiDiscoverDatabaseConfigureIAMPolicyEvent,
uiDiscoverDesktopActiveDirectoryToolsInstallEvent,
uiDiscoverDesktopActiveDirectoryConfigureEvent,
uiDiscoverAutoDiscoveredResourcesEvent,
uiDiscoverPrincipalsConfigureEvent,
uiDiscoverTestConnectionEvent,
uiDiscoverCompletedEvent:
var discoverEvent DiscoverEventData
if err := json.Unmarshal([]byte(*req.EventData), &discoverEvent); err != nil {

View file

@ -138,6 +138,13 @@ enum DiscoverResource {
DISCOVER_RESOURCE_APPLICATION_HTTP = 8;
DISCOVER_RESOURCE_APPLICATION_TCP = 9;
DISCOVER_RESOURCE_WINDOWS_DESKTOP = 10;
DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS = 11;
DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT = 12;
DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED = 13;
DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED = 14;
DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP = 15;
DISCOVER_RESOURCE_DATABASE_MYSQL_GCP = 16;
DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP = 17;
}
// DiscoverResourceMetadata contains common metadata identifying resource type being added.

View file

@ -17,6 +17,7 @@
import useAttempt from 'shared/hooks/useAttemptNext';
import useTeleport from 'teleport/useTeleport';
import { useDiscover } from 'teleport/Discover/useDiscover';
// import { usePoll } from 'teleport/Discover/Shared/usePoll';
import { Database } from '../resources';
@ -36,6 +37,7 @@ export function useCreateDatabase(props: AgentStepProps) {
const ctx = useTeleport();
const clusterId = ctx.storeUser.getClusterId();
const { attempt, setAttempt } = useAttempt('');
const { emitErrorEvent } = useDiscover();
// const [pollTimeout, setPollTimeout] = useState(0);
// const [pollActive, setPollActive] = useState(false);
@ -116,7 +118,12 @@ export function useCreateDatabase(props: AgentStepProps) {
// request operation is only a CREATE operation).
// if (!newDb || db.name != newDb.name) {
try {
const createdDb = await ctx.databaseService.createDatabase(clusterId, db);
const createdDb = await ctx.databaseService
.createDatabase(clusterId, db)
.catch((error: Error) => {
emitErrorEvent(error.message);
throw error;
});
// setNewDb(db);
props.updateAgentMeta({
...(props.agentMeta as DbMeta),

View file

@ -26,6 +26,8 @@ import {
} from 'teleport/Discover/Shared/JoinTokenContext';
import { PingTeleportProvider } from 'teleport/Discover/Shared/PingTeleportContext';
import { userContext } from 'teleport/mocks/contexts';
import { DiscoverProvider } from 'teleport/Discover/useDiscover';
import { FeaturesContextProvider } from 'teleport/FeaturesContext';
import DownloadScript from './DownloadScript';
@ -139,17 +141,25 @@ const Provider = props => {
const ctx = createTeleportContext();
return (
<MemoryRouter>
<MemoryRouter
initialEntries={[
{ pathname: cfg.routes.discover, state: { entity: 'database' } },
]}
>
<ContextProvider ctx={ctx}>
<JoinTokenProvider timeout={props.timeout || 100000}>
<PingTeleportProvider
timeout={props.timeout || 100000}
interval={props.interval || 100000}
resourceKind={ResourceKind.Database}
>
{props.children}
</PingTeleportProvider>
</JoinTokenProvider>
<FeaturesContextProvider value={[]}>
<DiscoverProvider>
<JoinTokenProvider timeout={props.timeout || 100000}>
<PingTeleportProvider
timeout={props.timeout || 100000}
interval={props.interval || 100000}
resourceKind={ResourceKind.Database}
>
{props.children}
</PingTeleportProvider>
</JoinTokenProvider>
</DiscoverProvider>
</FeaturesContextProvider>
</ContextProvider>
</MemoryRouter>
);

View file

@ -101,7 +101,7 @@ export default function Container(
<ActionButtons
onProceed={() => null}
disableProceed={true}
onSkip={props.nextStep}
onSkip={() => props.nextStep(0)}
/>
</Box>
)}
@ -118,7 +118,7 @@ export default function Container(
<ActionButtons
onProceed={() => null}
disableProceed={true}
onSkip={props.nextStep}
onSkip={() => props.nextStep(0)}
/>
</Box>
}
@ -137,7 +137,7 @@ export default function Container(
<ActionButtons
onProceed={() => null}
disableProceed={true}
onSkip={props.nextStep}
onSkip={() => props.nextStep(0)}
/>
</Box>
)}
@ -242,7 +242,7 @@ export function DownloadScript(
<ActionButtons
onProceed={handleNextStep}
disableProceed={poll.state !== 'success' || props.labels.length === 0}
onSkip={props.nextStep}
onSkip={() => props.nextStep(0)}
/>
</Box>
);

View file

@ -18,12 +18,14 @@ import { useEffect, useState } from 'react';
import useAttempt from 'shared/hooks/useAttemptNext';
import TeleportContext from 'teleport/teleportContext';
import { useDiscover } from 'teleport/Discover/useDiscover';
import type { AgentStepProps } from '../../types';
import type { DatabaseIamPolicyResponse } from 'teleport/services/databases';
export function useIamPolicy({ ctx, props }: Props) {
const { attempt, run } = useAttempt('');
const { emitErrorEvent } = useDiscover();
const [iamPolicy, setIamPolicy] = useState<DatabaseIamPolicyResponse>();
@ -41,6 +43,10 @@ export function useIamPolicy({ ctx, props }: Props) {
ctx.databaseService
.fetchDatabaseIamPolicy(clusterId, props.agentMeta.resourceName)
.then(setIamPolicy)
.catch((error: Error) => {
emitErrorEvent(error.message);
throw error;
})
);
}

View file

@ -23,7 +23,7 @@ import { useJoinTokenValue } from 'teleport/Discover/Shared/JoinTokenContext';
import { ResourceKind } from 'teleport/Discover/Shared';
import { resourceKindToJoinRole } from 'teleport/Discover/Shared/ResourceKind';
import { DbMeta } from '../../useDiscover';
import { DbMeta, useDiscover } from '../../useDiscover';
import type { AgentStepProps } from '../../types';
import type { Database } from '../resources';
@ -32,6 +32,7 @@ export function useMutualTls({ ctx, props }: Props) {
const { attempt, run } = useAttempt('');
const prevFetchedJoinToken = useJoinTokenValue();
const { emitErrorEvent } = useDiscover();
const [joinToken, setJoinToken] = useState(prevFetchedJoinToken);
const meta = props.agentMeta as DbMeta;
const clusterId = ctx.storeUser.getClusterId();
@ -52,6 +53,10 @@ export function useMutualTls({ ctx, props }: Props) {
method: 'token',
})
.then(setJoinToken)
.catch((error: Error) => {
emitErrorEvent(`error with fetching join token: ${error.message}`);
throw error;
})
);
}
// Ensure runs only once.
@ -71,6 +76,12 @@ export function useMutualTls({ ctx, props }: Props) {
caCert,
})
.then(() => props.nextStep())
.catch((error: Error) => {
emitErrorEvent(
`error with update database with caCert: ${error.message}`
);
throw error;
})
);
}

View file

@ -32,6 +32,7 @@ import { DownloadScript } from 'teleport/Discover/Database/DownloadScript';
import { MutualTls } from 'teleport/Discover/Database/MutualTls';
import { TestConnection } from 'teleport/Discover/Database/TestConnection';
import { IamPolicy } from 'teleport/Discover/Database/IamPolicy';
import { DiscoverEvent } from 'teleport/services/userEvent';
export const DatabaseResource: Resource<Database> = {
kind: ResourceKind.Database,
@ -52,14 +53,17 @@ export const DatabaseResource: Resource<Database> = {
{
title: 'Register a Database',
component: CreateDatabase,
eventName: DiscoverEvent.DatabaseRegister,
},
{
title: 'Deploy Database Service',
component: DownloadScript,
eventName: DiscoverEvent.DeployService,
},
{
title: 'Configure IAM Policy',
component: IamPolicy,
eventName: DiscoverEvent.DatabaseConfigureIAMPolicy,
},
];
@ -70,14 +74,17 @@ export const DatabaseResource: Resource<Database> = {
{
title: 'Register a Database',
component: CreateDatabase,
eventName: DiscoverEvent.DatabaseRegister,
},
{
title: 'Deploy Database Service',
component: DownloadScript,
eventName: DiscoverEvent.DeployService,
},
{
title: 'Configure mTLS',
component: MutualTls,
eventName: DiscoverEvent.DatabaseConfigureMTLS,
},
];
@ -88,6 +95,7 @@ export const DatabaseResource: Resource<Database> = {
return [
{
title: 'Select Resource Type',
eventName: DiscoverEvent.ResourceSelection,
},
{
title: 'Configure Resource',
@ -96,14 +104,18 @@ export const DatabaseResource: Resource<Database> = {
{
title: 'Set Up Access',
component: SetupAccess,
eventName: DiscoverEvent.PrincipalsConfigure,
},
{
title: 'Test Connection',
component: TestConnection,
eventName: DiscoverEvent.TestConnection,
manuallyEmitSuccessEvent: true,
},
{
title: 'Finished',
component: Finished,
eventName: DiscoverEvent.Completed,
hide: true,
},
];

View file

@ -96,6 +96,10 @@ const verticalTransitionStyles = {
};
import { State } from 'teleport/Discover/useDiscover';
import {
DiscoverEvent,
DiscoverEventStatus,
} from 'teleport/services/userEvent';
export function ConnectTeleport(props: State) {
const [currentStep, setCurrentStep] = useState(StepKind.RunConfigureScript);
@ -156,7 +160,16 @@ export function ConnectTeleport(props: State) {
{currentStep === StepKind.RunConfigureScript && (
<Suspense fallback={<RunConfigureScriptLoading />}>
<RunConfigureScript
onNext={() => setCurrentStep(StepKind.CopyOutput)}
onNext={() => {
props.emitEvent(
{ stepStatus: DiscoverEventStatus.Success },
{
eventName:
DiscoverEvent.DesktopActiveDirectoryConfigure,
}
);
setCurrentStep(StepKind.CopyOutput);
}}
/>
</Suspense>
)}

View file

@ -5,7 +5,7 @@ import { Box, ButtonPrimary, Text } from 'design';
import { DesktopItem } from 'teleport/Discover/Desktop/DiscoverDesktops/DesktopItem';
import { Header } from 'teleport/Discover/Shared';
import { State } from 'teleport/Discover/useDiscover';
import { useDiscover } from 'teleport/Discover/useDiscover';
import { ProxyDesktopServiceDiagram } from 'teleport/Discover/Desktop/DiscoverDesktops/ProxyDesktopServiceDiagram';
import { usePoll } from 'teleport/Discover/Shared/usePoll';
import { useTeleport } from 'teleport';
@ -13,6 +13,7 @@ import useStickyClusterId from 'teleport/useStickyClusterId';
import { usePingTeleport } from 'teleport/Discover/Shared/PingTeleportContext';
import cfg from 'teleport/config';
import { NavLink } from 'teleport/components/Router';
import { DiscoverEventStatus } from 'teleport/services/userEvent';
import type { WindowsDesktopService } from 'teleport/services/desktops';
@ -82,8 +83,9 @@ const TimedOutTitle = styled.div`
font-size: 16px;
`;
export function DiscoverDesktops(props: State) {
export function DiscoverDesktops() {
const ctx = useTeleport();
const { emitEvent, nextStep } = useDiscover();
const { result: desktopService } = usePingTeleport<WindowsDesktopService>();
@ -107,6 +109,14 @@ export function DiscoverDesktops(props: State) {
const ref = useRef<HTMLDivElement>();
function handleNextStep() {
emitEvent(
{ stepStatus: DiscoverEventStatus.Success },
{ autoDiscoverResourcesCount: result.agents.length }
);
nextStep();
}
const desktops = [];
if (result && result.agents) {
@ -215,7 +225,7 @@ export function DiscoverDesktops(props: State) {
</Desktops>
<Buttons>
<ButtonPrimary width="165px" mr={3} onClick={() => props.nextStep()}>
<ButtonPrimary width="165px" mr={3} onClick={handleNextStep}>
Finish
</ButtonPrimary>
</Buttons>

View file

@ -27,6 +27,7 @@ import { InstallActiveDirectory } from 'teleport/Discover/Desktop/InstallActiveD
import { Resource } from 'teleport/Discover/flow';
import { DesktopWrapper } from 'teleport/Discover/Desktop/DesktopWrapper';
import { DiscoverEvent } from 'teleport/services/userEvent';
export const DesktopResource: Resource = {
kind: ResourceKind.Desktop,
@ -46,22 +47,30 @@ export const DesktopResource: Resource = {
views: [
{
title: 'Select Resource Type',
eventName: DiscoverEvent.ResourceSelection,
},
{
title: 'Install Active Directory',
component: InstallActiveDirectory,
eventName: DiscoverEvent.DesktopActiveDirectoryToolsInstall,
},
{
title: 'Connect Teleport',
component: ConnectTeleport,
// Sub-step events are handled inside its component.
// This eventName defines the event to emit for the `last` sub-step.
eventName: DiscoverEvent.DeployService,
},
{
title: 'Discover Desktops',
component: DiscoverDesktops,
eventName: DiscoverEvent.AutoDiscoveredResources,
manuallyEmitSuccessEvent: true,
},
{
title: 'Finished',
component: Finished,
eventName: DiscoverEvent.Completed,
hide: true,
},
],

View file

@ -27,6 +27,16 @@ import { Discover } from 'teleport/Discover/Discover';
import { FeaturesContextProvider } from 'teleport/FeaturesContext';
import { fullAcl } from 'teleport/mocks/contexts';
import { getOSSFeatures } from 'teleport/features';
import cfg from 'teleport/config';
const crypto = require('crypto');
// eslint-disable-next-line jest/require-hook
Object.defineProperty(globalThis, 'crypto', {
value: {
randomUUID: () => crypto.randomUUID(),
},
});
const userContextJson = {
authType: 'sso',
@ -56,7 +66,11 @@ describe('discover', () => {
});
return render(
<MemoryRouter initialEntries={[{ state: { entity: initialEntry } }]}>
<MemoryRouter
initialEntries={[
{ pathname: cfg.routes.discover, state: { entity: initialEntry } },
]}
>
<TeleportContextProvider ctx={ctx}>
<FeaturesContextProvider value={getOSSFeatures()}>
<Discover />

View file

@ -75,7 +75,7 @@ function DiscoverContent() {
<Prompt
message={nextLocation => {
if (nextLocation.pathname === cfg.routes.discover) return true;
return 'Are you sure you want to exit the “Add New Resource” workflow? Youll have to start from the beginning next time.';
return 'Are you sure you want to exit the "Enroll New Resource” workflow? Youll have to start from the beginning next time.';
}}
when={selectedResource.shouldPrompt(currentStep)}
/>

View file

@ -26,6 +26,8 @@ import {
} from 'teleport/Discover/Shared/JoinTokenContext';
import { PingTeleportProvider } from 'teleport/Discover/Shared/PingTeleportContext';
import { userContext } from 'teleport/mocks/contexts';
import { DiscoverProvider } from 'teleport/Discover/useDiscover';
import { FeaturesContextProvider } from 'teleport/FeaturesContext';
import HelmChart from './HelmChart';
@ -126,17 +128,25 @@ const Provider = props => {
const ctx = createTeleportContext();
return (
<MemoryRouter>
<MemoryRouter
initialEntries={[
{ pathname: cfg.routes.discover, state: { entity: 'database' } },
]}
>
<ContextProvider ctx={ctx}>
<JoinTokenProvider timeout={props.timeout || 100000}>
<PingTeleportProvider
timeout={props.timeout || 100000}
interval={props.interval || 100000}
resourceKind={ResourceKind.Kubernetes}
>
{props.children}
</PingTeleportProvider>
</JoinTokenProvider>
<FeaturesContextProvider value={[]}>
<DiscoverProvider>
<JoinTokenProvider timeout={props.timeout || 100000}>
<PingTeleportProvider
timeout={props.timeout || 100000}
interval={props.interval || 100000}
resourceKind={ResourceKind.Kubernetes}
>
{props.children}
</PingTeleportProvider>
</JoinTokenProvider>
</DiscoverProvider>
</FeaturesContextProvider>
</ContextProvider>
</MemoryRouter>
);

View file

@ -20,6 +20,7 @@ import { Kubernetes } from 'design/Icon';
import { Finished, ResourceKind } from 'teleport/Discover/Shared';
import { Resource } from 'teleport/Discover/flow';
import { DiscoverEvent } from 'teleport/services/userEvent';
import { KubeWrapper } from './KubeWrapper';
import { SetupAccess } from './SetupAccess';
@ -39,23 +40,29 @@ export const KubernetesResource: Resource = {
views: [
{
title: 'Select Resource Type',
eventName: DiscoverEvent.ResourceSelection,
},
{
title: 'Configure Resource',
component: HelmChart,
eventName: DiscoverEvent.DeployService,
},
{
title: 'Set Up Access',
component: SetupAccess,
eventName: DiscoverEvent.PrincipalsConfigure,
},
{
title: 'Test Connection',
component: TestConnection,
eventName: DiscoverEvent.TestConnection,
manuallyEmitSuccessEvent: true,
},
{
title: 'Finished',
component: Finished,
hide: true,
eventName: DiscoverEvent.Completed,
},
],
};

View file

@ -29,6 +29,16 @@ import { DiscoverProvider } from 'teleport/Discover/useDiscover';
import { FeaturesContextProvider } from 'teleport/FeaturesContext';
import { fullAccess, fullAcl } from 'teleport/mocks/contexts';
import { getOSSFeatures } from 'teleport/features';
import cfg from 'teleport/config';
const crypto = require('crypto');
// eslint-disable-next-line jest/require-hook
Object.defineProperty(globalThis, 'crypto', {
value: {
randomUUID: () => crypto.randomUUID(),
},
});
const userContextJson = {
authType: 'sso',
@ -58,7 +68,7 @@ describe('select resource', () => {
});
return render(
<MemoryRouter>
<MemoryRouter initialEntries={[{ pathname: cfg.routes.discover }]}>
<TeleportContextProvider ctx={ctx}>
<FeaturesContextProvider value={getOSSFeatures()}>
<DiscoverProvider>

View file

@ -25,6 +25,10 @@ import useTeleport from 'teleport/useTeleport';
import { Acl } from 'teleport/services/user';
import { ResourceKind, Header, HeaderSubtitle } from 'teleport/Discover/Shared';
import {
DiscoverEvent,
DiscoverEventStatus,
} from 'teleport/services/userEvent';
import { ApplicationResource } from '../Application/ApplicationResource';
import { DatabaseResource } from '../Database/DatabaseResource';
@ -32,6 +36,7 @@ import { DesktopResource } from '../Desktop/DesktopResource';
import { KubernetesResource } from '../Kubernetes/KubernetesResource';
import { ServerResource } from '../Server/ServerResource';
import { DatabaseEngine, DatabaseLocation } from '../Database/resources';
import { useDiscover } from '../useDiscover';
import k8sIcon from './assets/kubernetes.png';
import serverIcon from './assets/server.png';
@ -67,6 +72,7 @@ interface SelectResourceProps<T = any> {
export function SelectResource(props: SelectResourceProps) {
const ctx = useTeleport();
const { emitEvent } = useDiscover();
const userContext = ctx.storeUser.state;
const { acl } = userContext;
@ -141,6 +147,7 @@ export function SelectResource(props: SelectResourceProps) {
state.engine === DatabaseEngine.MySQL
) {
props.onNext();
return;
}
}
@ -150,10 +157,12 @@ export function SelectResource(props: SelectResourceProps) {
state.engine === DatabaseEngine.MySQL
) {
props.onNext();
return;
}
}
// Unsupported databases will default to the modal popup.
emitEvent({ stepStatus: DiscoverEventStatus.Success });
return setShowAddDB(true);
}}
/>
@ -161,7 +170,13 @@ export function SelectResource(props: SelectResourceProps) {
{props.selectedResourceKind === ResourceKind.Application && (
<ApplicationResource
disabled={disabled}
onProceed={() => setShowAddApp(true)}
onProceed={() => {
setShowAddApp(true);
emitEvent(
{ stepStatus: DiscoverEventStatus.Success },
{ eventName: DiscoverEvent.ResourceSelection }
);
}}
/>
)}
{props.selectedResourceKind === ResourceKind.Desktop && (

View file

@ -26,6 +26,8 @@ import {
import { PingTeleportProvider } from 'teleport/Discover/Shared/PingTeleportContext';
import { userContext } from 'teleport/Main/fixtures';
import { ResourceKind } from 'teleport/Discover/Shared';
import { DiscoverProvider } from 'teleport/Discover/useDiscover';
import { FeaturesContextProvider } from 'teleport/FeaturesContext';
import DownloadScript from './DownloadScript';
@ -118,17 +120,25 @@ const Provider = props => {
const ctx = createTeleportContext();
return (
<MemoryRouter>
<MemoryRouter
initialEntries={[
{ pathname: cfg.routes.discover, state: { entity: 'database' } },
]}
>
<ContextProvider ctx={ctx}>
<JoinTokenProvider timeout={props.timeout || 100000}>
<PingTeleportProvider
timeout={props.timeout || 100000}
interval={props.interval || 100000}
resourceKind={ResourceKind.Server}
>
{props.children}
</PingTeleportProvider>
</JoinTokenProvider>
<FeaturesContextProvider value={[]}>
<DiscoverProvider>
<JoinTokenProvider timeout={props.timeout || 100000}>
<PingTeleportProvider
timeout={props.timeout || 100000}
interval={props.interval || 100000}
resourceKind={ResourceKind.Server}
>
{props.children}
</PingTeleportProvider>
</JoinTokenProvider>
</DiscoverProvider>
</FeaturesContextProvider>
</ContextProvider>
</MemoryRouter>
);

View file

@ -23,6 +23,7 @@ import { DownloadScript } from 'teleport/Discover/Server/DownloadScript';
import { SetupAccess } from 'teleport/Discover/Server/SetupAccess';
import { TestConnection } from 'teleport/Discover/Server/TestConnection';
import { ResourceKind, Finished } from 'teleport/Discover/Shared';
import { DiscoverEvent } from 'teleport/services/userEvent';
import { ServerWrapper } from './ServerWrapper';
@ -39,23 +40,29 @@ export const ServerResource: Resource = {
views: [
{
title: 'Select Resource Type',
eventName: DiscoverEvent.ResourceSelection,
},
{
title: 'Configure Resource',
component: DownloadScript,
eventName: DiscoverEvent.DeployService,
},
{
title: 'Set Up Access',
component: SetupAccess,
eventName: DiscoverEvent.PrincipalsConfigure,
},
{
title: 'Test Connection',
component: TestConnection,
eventName: DiscoverEvent.TestConnection,
manuallyEmitSuccessEvent: true,
},
{
title: 'Finished',
component: Finished,
hide: true,
eventName: DiscoverEvent.Completed,
},
],
};

View file

@ -18,12 +18,13 @@ import { useState } from 'react';
import useAttempt from 'shared/hooks/useAttemptNext';
import useTeleport from 'teleport/useTeleport';
import { useDiscover } from 'teleport/Discover/useDiscover';
import { DiscoverEventStatus } from 'teleport/services/userEvent';
import type {
ConnectionDiagnostic,
ConnectionDiagnosticRequest,
} from 'teleport/services/agents';
import type { AgentStepProps } from '../../types';
export function useConnectionDiagnostic(props: AgentStepProps) {
@ -31,14 +32,42 @@ export function useConnectionDiagnostic(props: AgentStepProps) {
const { attempt, run } = useAttempt('');
const [diagnosis, setDiagnosis] = useState<ConnectionDiagnostic>();
const [ranDiagnosis, setRanDiagnosis] = useState(false);
const { emitErrorEvent, emitEvent } = useDiscover();
const access = ctx.storeUser.getConnectionDiagnosticAccess();
const canTestConnection = access.create && access.edit && access.read;
function runConnectionDiagnostic(req: ConnectionDiagnosticRequest) {
setDiagnosis(null); // reset since user's can re-test connection.
setRanDiagnosis(true);
run(() =>
ctx.agentService.createConnectionDiagnostic(req).then(setDiagnosis)
ctx.agentService
.createConnectionDiagnostic(req)
.then(diag => {
setDiagnosis(diag);
// The request may succeed, but the connection
// test itself can fail:
if (!diag.success) {
// Append all possible errors:
const errors: string[] = [];
diag.traces.forEach(trace => {
if (trace.status === 'failed') {
errors.push(
`[${trace.traceType}] ${trace.error} (${trace.details})`
);
}
});
emitErrorEvent(`testing failed: ${errors.join('\n')}`);
} else {
emitEvent({ stepStatus: DiscoverEventStatus.Success });
}
})
.catch((error: Error) => {
emitErrorEvent(error.message);
throw error;
})
);
}
@ -48,7 +77,15 @@ export function useConnectionDiagnostic(props: AgentStepProps) {
attempt,
runConnectionDiagnostic,
diagnosis,
nextStep: () => props.nextStep(),
nextStep: () => {
if (!ranDiagnosis) {
emitEvent({ stepStatus: DiscoverEventStatus.Skipped });
}
// else either a failed or success event would've been
// already sent for each test connection, so we don't need
// to send anything here.
props.nextStep();
},
prevStep: props.prevStep,
canTestConnection,
username,

View file

@ -1,3 +1,19 @@
/**
* Copyright 2022 Gravitational, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useCallback, useContext, useEffect, useState } from 'react';
import { useTeleport } from 'teleport';
@ -7,6 +23,8 @@ import {
resourceKindToJoinRole,
} from 'teleport/Discover/Shared/ResourceKind';
import { useDiscover } from '../useDiscover';
import type { AgentLabel } from 'teleport/services/agents';
import type { JoinToken, JoinMethod } from 'teleport/services/joinToken';
@ -90,6 +108,7 @@ export function useJoinToken(
} {
const ctx = useTeleport();
const tokenContext = useContext(joinTokenContext);
const { emitErrorEvent } = useDiscover();
function run() {
abortController = new AbortController();
@ -116,8 +135,9 @@ export function useJoinToken(
tokenContext.setJoinToken(token);
tokenContext.startTimer();
})
.catch(error => {
.catch((error: Error) => {
cachedJoinTokenResult.error = error;
emitErrorEvent(error.message);
}),
};

View file

@ -6,6 +6,8 @@ import { INTERNAL_RESOURCE_ID_LABEL_KEY } from 'teleport/services/joinToken';
import { useJoinTokenValue } from 'teleport/Discover/Shared/JoinTokenContext';
import { ResourceKind } from 'teleport/Discover/Shared/ResourceKind';
import { useDiscover } from '../useDiscover';
interface PingTeleportContextState<T> {
active: boolean;
start: () => void;
@ -28,6 +30,7 @@ export function PingTeleportProvider<T>(props: {
const [active, setActive] = useState(false);
const [timeout, setPollTimeout] = useState<number>(null);
const { emitErrorEvent } = useDiscover();
// alternateSearchTerm when set will be used as the search term
// instead of the default search term which is the internal resource ID.
@ -82,6 +85,8 @@ export function PingTeleportProvider<T>(props: {
useEffect(() => {
if (active && Date.now() > timeout) {
// This means the polling timed out.
emitErrorEvent('polling for resource discovery has timed out');
setActive(false);
}
}, [active, timeout, timedOut]);

View file

@ -14,7 +14,12 @@
* limitations under the License.
*/
import { DiscoverEventResource } from 'teleport/services/userEvent';
import { DatabaseEngine, DatabaseLocation } from '../Database/resources';
import type { JoinRole } from 'teleport/services/joinToken';
import type { Database } from '../Database/resources';
export enum ResourceKind {
Application,
@ -38,3 +43,69 @@ export function resourceKindToJoinRole(kind: ResourceKind): JoinRole {
return 'Node';
}
}
export function resourceKindToEventResource(
kind: ResourceKind,
resourceState: any
): DiscoverEventResource {
switch (kind) {
case ResourceKind.Database:
const { engine, location } = resourceState as Database;
if (location === DatabaseLocation.AWS) {
if (engine === DatabaseEngine.PostgreSQL) {
return DiscoverEventResource.DatabasePostgresRds;
}
if (engine === DatabaseEngine.MySQL) {
return DiscoverEventResource.DatabaseMysqlRds;
}
if (engine === DatabaseEngine.SQLServer) {
return DiscoverEventResource.DatabaseSqlServerRds;
}
if (engine === DatabaseEngine.RedShift) {
return DiscoverEventResource.DatabasePostgresRedshift;
}
}
if (location === DatabaseLocation.SelfHosted) {
if (engine === DatabaseEngine.PostgreSQL) {
return DiscoverEventResource.DatabasePostgresSelfHosted;
}
if (engine === DatabaseEngine.MySQL) {
return DiscoverEventResource.DatabaseMysqlSelfHosted;
}
if (engine === DatabaseEngine.Mongo) {
return DiscoverEventResource.DatabaseMongodbSelfHosted;
}
if (engine === DatabaseEngine.SQLServer) {
return DiscoverEventResource.DatabaseSqlServerSelfHosted;
}
if (engine === DatabaseEngine.Redis) {
return DiscoverEventResource.DatabaseRedisSelfHosted;
}
}
if (location === DatabaseLocation.GCP) {
if (engine === DatabaseEngine.PostgreSQL) {
return DiscoverEventResource.DatabasePostgresGcp;
}
if (engine === DatabaseEngine.MySQL) {
return DiscoverEventResource.DatabaseMysqlGcp;
}
if (engine === DatabaseEngine.SQLServer) {
return DiscoverEventResource.DatabaseMysqlGcp;
}
}
console.error(`resource database event not defined for ${resourceState}`);
return null;
case ResourceKind.Desktop:
return DiscoverEventResource.WindowsDesktop;
case ResourceKind.Kubernetes:
return DiscoverEventResource.Kubernetes;
case ResourceKind.Server:
return DiscoverEventResource.Server;
case ResourceKind.Application:
return DiscoverEventResource.ApplicationHttp;
default:
console.error(`resource event not defined for ${resourceState}`);
}
}

View file

@ -15,11 +15,16 @@ limitations under the License.
*/
import React from 'react';
import { MemoryRouter } from 'react-router';
import { renderHook, act } from '@testing-library/react-hooks';
import { baseContext } from 'teleport/mocks/contexts';
import makeUserContext from 'teleport/services/user/makeUserContext';
import { ContextProvider, Context as TeleportContext } from 'teleport';
import { FeaturesContextProvider } from 'teleport/FeaturesContext';
import { DiscoverProvider } from 'teleport/Discover/useDiscover';
import cfg from 'teleport/config';
import { userEventService } from 'teleport/services/userEvent';
import { ResourceKind } from '../ResourceKind';
@ -32,17 +37,35 @@ import type {
NodeMeta,
} from 'teleport/Discover/useDiscover';
const crypto = require('crypto');
// eslint-disable-next-line jest/require-hook
Object.defineProperty(globalThis, 'crypto', {
value: {
randomUUID: () => crypto.randomUUID(),
},
});
describe('onProceed correctly deduplicates, removes static traits, updates meta, and calls updateUser', () => {
const ctx = createTeleportContext();
jest.spyOn(ctx.userService, 'fetchUser').mockResolvedValue(getMockUser());
jest.spyOn(ctx.userService, 'updateUser').mockResolvedValue(null);
jest.spyOn(ctx.userService, 'applyUserTraits').mockResolvedValue(null);
jest
.spyOn(userEventService, 'captureDiscoverEvent')
.mockResolvedValue(null as never); // return value does not matter but required by ts
let wrapper;
beforeEach(() => {
wrapper = ({ children }) => (
<ContextProvider ctx={ctx}>{children}</ContextProvider>
<MemoryRouter initialEntries={[{ pathname: cfg.routes.discover }]}>
<ContextProvider ctx={ctx}>
<FeaturesContextProvider value={[]}>
<DiscoverProvider>{children}</DiscoverProvider>
</FeaturesContextProvider>
</ContextProvider>
</MemoryRouter>
);
});
@ -296,7 +319,13 @@ describe('static and dynamic traits are correctly separated and correctly create
};
const wrapper = ({ children }) => (
<ContextProvider ctx={ctx}>{children}</ContextProvider>
<MemoryRouter initialEntries={[{ pathname: cfg.routes.discover }]}>
<ContextProvider ctx={ctx}>
<FeaturesContextProvider value={[]}>
<DiscoverProvider>{children}</DiscoverProvider>
</FeaturesContextProvider>
</ContextProvider>
</MemoryRouter>
);
const { result, waitForNextUpdate } = renderHook(

View file

@ -20,11 +20,12 @@ import useAttempt from 'shared/hooks/useAttemptNext';
import { arrayStrDiff } from 'teleport/lib/util';
import useTeleport from 'teleport/useTeleport';
import { Option } from 'teleport/Discover/Shared/SelectCreatable';
import { useDiscover } from 'teleport/Discover/useDiscover';
import { ResourceKind } from '../ResourceKind';
import type { User, UserTraits } from 'teleport/services/user';
import type { DbMeta, KubeMeta, NodeMeta } from 'teleport/Discover/useDiscover';
import type { User, UserTraits } from 'teleport/services/user';
import type { AgentStepProps } from '../../types';
// useUserTraits handles:
@ -35,6 +36,7 @@ import type { AgentStepProps } from '../../types';
// - provides utility function that makes data objects (type Option) for react-select component
export function useUserTraits(props: AgentStepProps) {
const ctx = useTeleport();
const { emitErrorEvent } = useDiscover();
const [user, setUser] = useState<User>();
const { attempt, run, setAttempt, handleError } = useAttempt('processing');
@ -85,18 +87,19 @@ export function useUserTraits(props: AgentStepProps) {
);
}
useEffect(
function initFetchUserTraits() {
run(() =>
ctx.userService.fetchUser(ctx.storeUser.getUsername()).then(setUser)
);
},
[ctx.storeUser, ctx.userService, run]
);
useEffect(() => {
fetchUserTraits();
}, [ctx.storeUser, ctx.userService, run]);
function fetchUserTraits() {
run(() =>
ctx.userService.fetchUser(ctx.storeUser.getUsername()).then(setUser)
ctx.userService
.fetchUser(ctx.storeUser.getUsername())
.then(setUser)
.catch((error: Error) => {
emitErrorEvent(`error fetching user traits: ${error.message}`);
throw error;
})
);
}
@ -232,15 +235,24 @@ export function useUserTraits(props: AgentStepProps) {
updateResourceMetaDynamicTraits(newDynamicTraits);
setAttempt({ status: 'processing' });
try {
await ctx.userService.updateUser({
...user,
traits: {
...user.traits,
...newDynamicTraits,
},
await ctx.userService
.updateUser({
...user,
traits: {
...user.traits,
...newDynamicTraits,
},
})
.catch((error: Error) => {
emitErrorEvent(`error updating user traits: ${error.message}`);
throw error;
});
await ctx.userService.applyUserTraits().catch((error: Error) => {
emitErrorEvent(`error applying new user traits: ${error.message}`);
throw error;
});
await ctx.userService.applyUserTraits();
props.nextStep();
} catch (err) {
handleError(err);

View file

@ -18,6 +18,7 @@ import React from 'react';
import { ResourceKind } from 'teleport/Discover/Shared';
import { AgentStepComponent } from 'teleport/Discover/types';
import { DiscoverEvent } from 'teleport/services/userEvent';
type ViewFunction<T> = (t: T) => View[];
@ -35,6 +36,12 @@ export interface View {
hide?: boolean;
index?: number;
views?: View[];
eventName?: DiscoverEvent;
// manuallyEmitSuccessEvent is a flag that when true
// means success events will be sent by the children
// (current view component) instead of the default
// which is sent by the parent context.
manuallyEmitSuccessEvent?: boolean;
}
// computeViewChildrenSize calculates how many children a view has, without counting the first

View file

@ -0,0 +1,271 @@
/**
* Copyright 2023 Gravitational, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { MemoryRouter } from 'react-router';
import { renderHook, act } from '@testing-library/react-hooks';
import { createTeleportContext } from 'teleport/mocks/contexts';
import { ContextProvider } from 'teleport';
import {
DiscoverEvent,
DiscoverEventResource,
DiscoverEventStatus,
userEventService,
} from 'teleport/services/userEvent';
import { FeaturesContextProvider } from 'teleport/FeaturesContext';
import api from 'teleport/services/api';
import cfg from 'teleport/config';
import { useDiscover, DiscoverProvider } from './useDiscover';
import { ResourceKind } from './Shared';
const crypto = require('crypto');
// eslint-disable-next-line jest/require-hook
Object.defineProperty(globalThis, 'crypto', {
value: {
randomUUID: () => crypto.randomUUID(),
},
});
describe('emitting events', () => {
const ctx = createTeleportContext();
let wrapper;
beforeEach(() => {
jest.spyOn(api, 'get').mockResolvedValue([]); // required for fetchClusterAlerts
jest
.spyOn(userEventService, 'captureDiscoverEvent')
.mockResolvedValue(null as never); // return value does not matter but required by ts
wrapper = ({ children }) => (
<MemoryRouter
initialEntries={[
{ pathname: cfg.routes.discover, state: { entity: 'server' } },
]}
>
<ContextProvider ctx={ctx}>
<FeaturesContextProvider value={[]}>
<DiscoverProvider>{children}</DiscoverProvider>
</FeaturesContextProvider>
</ContextProvider>
</MemoryRouter>
);
});
afterEach(() => {
jest.resetAllMocks();
});
test('init the eventState state', async () => {
const { result } = renderHook(() => useDiscover(), {
wrapper,
});
// Test init hook.
expect(result.current.currentStep).toBe(0);
expect(result.current.selectedResourceKind).toEqual(ResourceKind.Server);
expect(result.current.selectedResource.kind).toEqual(ResourceKind.Server);
expect(result.current.currentStep).toBe(0);
expect(result.current.eventState).toEqual(
expect.objectContaining({
id: expect.any(String),
currEventName: DiscoverEvent.ResourceSelection,
resource: DiscoverEventResource.Server,
})
);
const eventId = result.current.eventState.id;
expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(1);
expect(userEventService.captureDiscoverEvent).toHaveBeenCalledWith(
expect.objectContaining({
event: DiscoverEvent.Started,
eventData: {
id: eventId,
resource: '',
stepStatus: DiscoverEventStatus.Success,
},
})
);
jest.resetAllMocks();
// Calling to update eventState again should not emit an event
// but update the state only.
await act(async () => {
result.current.onSelectResource(ResourceKind.Kubernetes);
});
expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(0);
expect(result.current.eventState).toEqual({
id: eventId,
currEventName: DiscoverEvent.ResourceSelection,
resource: DiscoverEventResource.Kubernetes,
});
});
test('incrementing view by one, emits success event', async () => {
const { result } = renderHook(() => useDiscover(), {
wrapper,
});
jest.resetAllMocks(); // to discount the initial start event.
const id = result.current.eventState.id;
// Test next step gets incremented by 1, passing in a non-number.
await act(async () => {
result.current.nextStep('non-number' as any);
});
expect(result.current.currentStep).toBe(1);
expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(1);
expect(userEventService.captureDiscoverEvent).toHaveBeenCalledWith(
expect.objectContaining({
event: DiscoverEvent.ResourceSelection,
eventData: {
id,
resource: DiscoverEventResource.Server,
stepStatus: DiscoverEventStatus.Success,
},
})
);
// Test the `eventState` got updated to the next view.
expect(result.current.eventState).toEqual({
id,
currEventName: DiscoverEvent.DeployService,
resource: DiscoverEventResource.Server,
});
jest.resetAllMocks();
// Test passing in nothing, increments by 1.
await act(async () => {
result.current.nextStep();
});
expect(result.current.currentStep).toBe(2);
expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(1);
expect(userEventService.captureDiscoverEvent).toHaveBeenCalledWith(
expect.objectContaining({
event: DiscoverEvent.DeployService,
eventData: {
id,
resource: DiscoverEventResource.Server,
stepStatus: DiscoverEventStatus.Success,
},
})
);
});
test('programatically skipping, emits skipped and one success event', async () => {
const { result } = renderHook(() => useDiscover(), {
wrapper,
});
jest.resetAllMocks(); // to discount the initial start event.
const id = result.current.eventState.id;
// Test all skipped steps have been emitted.
await act(async () => {
result.current.nextStep(3);
});
expect(result.current.currentStep).toBe(3);
expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(3);
// Emit the current event.
expect(userEventService.captureDiscoverEvent).toHaveBeenNthCalledWith(
1,
expect.objectContaining({
event: DiscoverEvent.ResourceSelection,
eventData: {
id,
resource: DiscoverEventResource.Server,
stepStatus: DiscoverEventStatus.Success,
},
})
);
// Should have two skipped events.
expect(userEventService.captureDiscoverEvent).toHaveBeenNthCalledWith(
2,
expect.objectContaining({
event: DiscoverEvent.DeployService,
eventData: {
id,
resource: DiscoverEventResource.Server,
stepStatus: DiscoverEventStatus.Skipped,
},
})
);
expect(userEventService.captureDiscoverEvent).toHaveBeenNthCalledWith(
3,
expect.objectContaining({
event: DiscoverEvent.PrincipalsConfigure,
eventData: {
id,
resource: DiscoverEventResource.Server,
stepStatus: DiscoverEventStatus.Skipped,
},
})
);
});
test('user intentionally skipping, emits only skipped event', async () => {
const { result } = renderHook(() => useDiscover(), {
wrapper,
});
jest.resetAllMocks(); // to discount the initial start event.
const id = result.current.eventState.id;
await act(async () => {
result.current.nextStep(0);
});
expect(result.current.currentStep).toBe(1);
expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(1);
expect(userEventService.captureDiscoverEvent).toHaveBeenCalledWith(
expect.objectContaining({
event: DiscoverEvent.ResourceSelection,
eventData: {
id,
resource: DiscoverEventResource.Server,
stepStatus: DiscoverEventStatus.Skipped,
},
})
);
});
test('error event', async () => {
const { result } = renderHook(() => useDiscover(), {
wrapper,
});
jest.resetAllMocks(); // to discount the initial start event.
await act(async () => {
result.current.emitErrorEvent('some error message');
});
expect(result.current.currentStep).toBe(0);
expect(userEventService.captureDiscoverEvent).toHaveBeenCalledTimes(1);
expect(userEventService.captureDiscoverEvent).toHaveBeenCalledWith(
expect.objectContaining({
event: DiscoverEvent.ResourceSelection,
eventData: {
id: result.current.eventState.id,
resource: DiscoverEventResource.Server,
stepStatus: DiscoverEventStatus.Error,
stepStatusError: 'some error message',
},
})
);
});
});

View file

@ -14,15 +14,30 @@
* limitations under the License.
*/
import React, { useContext, useMemo, useState } from 'react';
import React, {
useContext,
useMemo,
useState,
useEffect,
useCallback,
} from 'react';
import { useLocation } from 'react-router';
import { useLocation, useHistory } from 'react-router';
import { ResourceKind } from 'teleport/Discover/Shared';
import {
DiscoverEventStatus,
DiscoverEventStepStatus,
DiscoverEvent,
DiscoverEventResource,
userEventService,
} from 'teleport/services/userEvent';
import cfg from 'teleport/config';
import { addIndexToViews, findViewAtIndex, Resource, View } from './flow';
import { resourceKindToEventResource } from './Shared/ResourceKind';
import { resources } from './resources';
import { DATABASES } from './Database/resources';
import type { Node } from 'teleport/services/nodes';
import type { Kube } from 'teleport/services/kube';
@ -57,21 +72,44 @@ interface DiscoverContextState<T = any> {
setResourceState: (value: T) => void;
updateAgentMeta: (meta: AgentMeta) => void;
views: View[];
emitErrorEvent(errorStr: string): void;
emitEvent(status: DiscoverEventStepStatus, custom?: CustomEventInput): void;
eventState: EventState;
}
type EventState = {
id: string;
currEventName: DiscoverEvent;
manuallyEmitSuccessEvent: boolean;
resource: DiscoverEventResource;
};
type CustomEventInput = {
eventName?: DiscoverEvent;
autoDiscoverResourcesCount?: number;
};
const discoverContext = React.createContext<DiscoverContextState>(null);
export function DiscoverProvider<T = any>(
props: React.PropsWithChildren<unknown>
) {
const location = useLocation<{ entity: string }>();
const history = useHistory();
const [currentStep, setCurrentStep] = useState(0);
const [selectedResourceKind, setSelectedResourceKind] =
useState<ResourceKind>(getKindFromString(location?.state?.entity));
const [agentMeta, setAgentMeta] = useState<AgentMeta>();
const [resourceState, setResourceState] = useState<T>();
const [resourceState, setResourceState] = useState<T>(() => {
// Pre-select the most popular one, to send of a start emit event
// on direct rendering the database view (user comes from clicking "add database")
if (selectedResourceKind === ResourceKind.Database) {
return DATABASES[0] as unknown as T;
}
});
const [eventState, setEventState] = useState<EventState>();
const selectedResource = resources.find(r => r.kind === selectedResourceKind);
const views = useMemo<View[]>(() => {
@ -82,16 +120,88 @@ export function DiscoverProvider<T = any>(
return addIndexToViews(selectedResource.views);
}, [selectedResource.views, resourceState]);
const emitEvent = useCallback(
(status: DiscoverEventStepStatus, custom?: CustomEventInput) => {
const { id, currEventName, resource } = eventState;
userEventService.captureDiscoverEvent({
event: custom?.eventName || currEventName,
eventData: {
id,
resource,
autoDiscoverResourcesCount: custom?.autoDiscoverResourcesCount,
...status,
},
});
},
[eventState]
);
useEffect(() => {
const emitAbortOrSuccessEvent = () => {
if (eventState.currEventName === DiscoverEvent.Completed) {
emitEvent({ stepStatus: DiscoverEventStatus.Success });
} else {
// TODO(lisa): this is temporary fill in as Application
// flow is not implemented yet and user can only abort
// on resource selection step.
if (selectedResourceKind === ResourceKind.Application) {
emitEvent(
{ stepStatus: DiscoverEventStatus.Aborted },
{ eventName: DiscoverEvent.ResourceSelection }
);
return;
}
emitEvent({ stepStatus: DiscoverEventStatus.Aborted });
}
};
// Emit abort event upon refreshing, going to different route
// (eg: copy and paste url) from same page, or closing tab/browser.
// Does not capture unmounting edge cases which is handled
// with the unmount logic below.
window.addEventListener('beforeunload', emitAbortOrSuccessEvent);
return () => {
// Emit abort event upon unmounting from going back or
// forward to a non-discover route or upon exiting from
// the exit prompt.
if (history.location.pathname !== cfg.routes.discover) {
emitAbortOrSuccessEvent();
}
window.removeEventListener('beforeunload', emitAbortOrSuccessEvent);
};
}, [eventState, history.location.pathname, emitEvent]);
useEffect(() => {
if (selectedResourceKind === ResourceKind.Database && !resourceState) {
// resourceState hasn't been loaded yet, this state is required to
// determine what type of database (engine/location) user
// selected to send the correct event. This state gets set when
// user selects a database (deployment type).
return;
}
updateEventState();
// Only run it once on init or when resource selection
// or resource state has changed.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedResourceKind, resourceState]);
function onSelectResource(kind: ResourceKind) {
setSelectedResourceKind(kind);
}
// nextStep takes the user to the next screen.
// The prop `numToIncrement` is used (>1) when we want to
// skip some number of steps.
// eg: particularly for Database flow, if there exists a
// database service, then we don't want to show the user
// the screen that lets them add a database server.
// nextStep takes the user to next screen and sends reporting events.
// The prop `numToIncrement` is used in the following ways:
// - numToIncrement === 0, will be interpreted as user intentionally
// skipping the current view, to go to the next view.
// - numToIncrement === 1 (default), will be interpreted as user finishing
// the current view and is ready to go next view.
// - numToIncrement > 1, will be interprested as skipping some steps FOR the user
// eg: for Database flow, if there exists a database service, then we don't want
// to show the user the screen that lets them add a database service.
function nextStep(numToIncrement = 1) {
// This function can be used in a way that HTML event
// get passed in which isn't a valid number.
@ -99,10 +209,40 @@ export function DiscoverProvider<T = any>(
numToIncrement = 1;
}
const nextView = findViewAtIndex(views, currentStep + numToIncrement);
const numNextSteps = numToIncrement || 1;
const nextView = findViewAtIndex(views, currentStep + numNextSteps);
if (nextView) {
setCurrentStep(currentStep + numToIncrement);
setCurrentStep(currentStep + numNextSteps);
setEventState({
...eventState,
currEventName: nextView.eventName,
manuallyEmitSuccessEvent: nextView.manuallyEmitSuccessEvent,
});
}
// Send reporting events:
// Emit event for the current view.
// If user intentionally skipped the current step, then
// skipped event will be emitted, else success.
if (!numToIncrement) {
emitEvent({ stepStatus: DiscoverEventStatus.Skipped });
} else if (!eventState.manuallyEmitSuccessEvent) {
emitEvent({ stepStatus: DiscoverEventStatus.Success });
}
// Whenever a numToIncrement is > 1, it means some steps (after the current view)
// are being skipped, which we should send events for.
if (numToIncrement > 1) {
for (let i = 1; i < numToIncrement; i++) {
const currView = findViewAtIndex(views, currentStep + i);
if (currView) {
emitEvent(
{ stepStatus: DiscoverEventStatus.Skipped },
{ eventName: currView.eventName }
);
}
}
}
}
@ -118,6 +258,63 @@ export function DiscoverProvider<T = any>(
setAgentMeta(meta);
}
function emitErrorEvent(errorStr = '') {
emitEvent({
stepStatus: DiscoverEventStatus.Error,
stepStatusError: errorStr,
});
}
// updateEventState is used when the Discover component updates in the following ways:
// - on initial render: sends the `start` event and will initialize the event state with
// the currently selected resource and create a unique ID that will tie the rest of
// the events that follow this `start` event.
// - on user updating `selectedResourceKind` (eg: server to kube)
// or `resourceState` (eg. postgres to mongo) which just updates the `eventState`
function updateEventState() {
const { eventName, manuallyEmitSuccessEvent } = findViewAtIndex(
views,
currentStep
);
const resource = resourceKindToEventResource(
selectedResourceKind,
resourceState
);
// Init the `eventState` and send the `started` event only once.
if (!eventState) {
// Generates a v4 UUID using a cryptographically secure
// random number.
const id = crypto.randomUUID();
setEventState({
id,
currEventName: eventName,
resource,
manuallyEmitSuccessEvent,
});
userEventService.captureDiscoverEvent({
event: DiscoverEvent.Started,
eventData: {
id,
stepStatus: DiscoverEventStatus.Success,
// Started event will be the ONLY event
// that won't expect a resource field.
resource: '' as any,
},
});
return;
}
setEventState({
...eventState,
currEventName: eventName,
resource,
manuallyEmitSuccessEvent,
});
}
const value: DiscoverContextState<T> = {
agentMeta,
currentStep,
@ -130,6 +327,9 @@ export function DiscoverProvider<T = any>(
setResourceState,
updateAgentMeta,
views,
emitErrorEvent,
emitEvent,
eventState,
};
return (

View file

@ -31,4 +31,7 @@ export const handlersTeleport = [
})
);
}),
rest.post(cfg.api.captureUserEventPath, (req, res, ctx) => {
return res(ctx.status(200));
}),
];

View file

@ -38,7 +38,7 @@ function makeTraces(traces: any): ConnectionDiagnosticTrace[] {
}
return traces.map(t => ({
traceType: t.trace_type,
traceType: t.traceType,
status: t.status?.toLowerCase(),
details: t.details,
error: t.error,

View file

@ -16,3 +16,80 @@ export enum CaptureEvent {
PreUserRecoveryCodesCopyClickEvent = 'tp.ui.recoveryCodesCopy.click',
PreUserRecoveryCodesPrintClickEvent = 'tp.ui.recoveryCodesPrint.click',
}
export enum DiscoverEvent {
Started = 'tp.ui.discover.started',
ResourceSelection = 'tp.ui.discover.resourceSelection',
DeployService = 'tp.ui.discover.deployService',
DatabaseRegister = 'tp.ui.discover.database.register',
DatabaseConfigureMTLS = 'tp.ui.discover.database.configure.mtls',
DatabaseConfigureIAMPolicy = 'tp.ui.discover.database.configure.iampolicy',
DesktopActiveDirectoryToolsInstall = 'tp.ui.discover.desktop.activeDirectory.tools.install',
DesktopActiveDirectoryConfigure = 'tp.ui.discover.desktop.activeDirectory.configure',
AutoDiscoveredResources = 'tp.ui.discover.autoDiscoveredResources',
PrincipalsConfigure = 'tp.ui.discover.principals.configure',
TestConnection = 'tp.ui.discover.testConnection',
Completed = 'tp.ui.discover.completed',
}
// DiscoverResource represents a resource type.
export enum DiscoverEventResource {
Server = 'DISCOVER_RESOURCE_SERVER',
Kubernetes = 'DISCOVER_RESOURCE_KUBERNETES',
DatabasePostgresSelfHosted = 'DISCOVER_RESOURCE_DATABASE_POSTGRES_SELF_HOSTED',
DatabaseMysqlSelfHosted = 'DISCOVER_RESOURCE_DATABASE_MYSQL_SELF_HOSTED',
DatabaseMongodbSelfHosted = 'DISCOVER_RESOURCE_DATABASE_MONGODB_SELF_HOSTED',
DatabasePostgresRds = 'DISCOVER_RESOURCE_DATABASE_POSTGRES_RDS',
DatabaseMysqlRds = 'DISCOVER_RESOURCE_DATABASE_MYSQL_RDS',
DatabaseSqlServerRds = 'DISCOVER_RESOURCE_DATABASE_SQLSERVER_RDS',
DatabasePostgresRedshift = 'DISCOVER_RESOURCE_DATABASE_POSTGRES_REDSHIFT',
DatabaseSqlServerSelfHosted = 'DISCOVER_RESOURCE_DATABASE_SQLSERVER_SELF_HOSTED',
DatabaseRedisSelfHosted = 'DISCOVER_RESOURCE_DATABASE_REDIS_SELF_HOSTED',
DatabasePostgresGcp = 'DISCOVER_RESOURCE_DATABASE_POSTGRES_GCP',
DatabaseMysqlGcp = 'DISCOVER_RESOURCE_DATABASE_MYSQL_GCP',
DatabaseSqlServerGcp = 'DISCOVER_RESOURCE_DATABASE_SQLSERVER_GCP',
ApplicationHttp = 'DISCOVER_RESOURCE_APPLICATION_HTTP',
ApplicationTcp = 'DISCOVER_RESOURCE_APPLICATION_TCP',
WindowsDesktop = 'DISCOVER_RESOURCE_WINDOWS_DESKTOP',
}
export enum DiscoverEventStatus {
Success = 'DISCOVER_STATUS_SUCCESS',
Skipped = 'DISCOVER_STATUS_SKIPPED',
Error = 'DISCOVER_STATUS_ERROR',
Aborted = 'DISCOVER_STATUS_ABORTED', // user exits the wizard
}
export type UserEvent = {
event: CaptureEvent;
alert?: string;
};
export type PreUserEvent = UserEvent & {
username: string;
mfaType?: string;
loginFlow?: string;
};
export type DiscoverEventRequest = Omit<UserEvent, 'event'> & {
event: DiscoverEvent;
eventData: DiscoverEventData;
};
export type DiscoverEventData = DiscoverEventStepStatus & {
id: string;
resource: DiscoverEventResource;
// AutoDiscoverResourcesCount is the number of
// auto-discovered resources in the Auto Discovering resources screen.
// This value is only considered for the 'tp.ui.discover.autoDiscoveredResources'.
autoDiscoverResourcesCount?: number;
};
export type DiscoverEventStepStatus = {
stepStatus: DiscoverEventStatus;
stepStatusError?: string;
};

View file

@ -1,18 +1,7 @@
import api from 'teleport/services/api';
import cfg from 'teleport/config';
import { CaptureEvent } from './types';
export type UserEvent = {
event: CaptureEvent;
alert?: string;
};
export type PreUserEvent = UserEvent & {
username: string;
mfaType?: string;
loginFlow?: string;
};
import { UserEvent, PreUserEvent, DiscoverEventRequest } from './types';
export const userEventService = {
captureUserEvent(userEvent: UserEvent) {
@ -32,4 +21,13 @@ export const userEventService = {
body: JSON.stringify({ ...preUserEvent }),
});
},
captureDiscoverEvent(event: DiscoverEventRequest) {
// using api.fetch instead of api.fetchJSON
// because we are not expecting a JSON response
void api.fetch(cfg.api.captureUserEventPath, {
method: 'POST',
body: JSON.stringify(event),
});
},
};