Best Keploy code snippet using telemetry.Normalize
handler.go
Source:handler.go
...170 counter := telemetry_registrationapi.StartListEntriesCall(h.Metrics)171 telemetry_common.AddCallerID(counter, getCallerID(ctx))172 defer counter.Done(&err)173 log := h.Log.WithField(telemetry.Method, telemetry.ListRegistrationsByParentID)174 request.Id, err = idutil.NormalizeSpiffeID(request.Id, idutil.AllowAny())175 if err != nil {176 log.WithError(err).Error("Failed to normalize SPIFFE ID")177 return nil, status.Error(codes.InvalidArgument, err.Error())178 }179 ds := h.getDataStore()180 listResponse, err := ds.ListRegistrationEntries(ctx,181 &datastore.ListRegistrationEntriesRequest{182 ByParentId: &wrappers.StringValue{183 Value: request.Id,184 },185 })186 if err != nil {187 log.WithError(err).Error("Failed to list entries by parent ID")188 return nil, status.Errorf(codes.Internal, "error trying to list entries by parent ID: %v", err)189 }190 return &common.RegistrationEntries{191 Entries: listResponse.Entries,192 }, nil193}194//ListBySelector returns all the Entries associated with the Selector195func (h *Handler) ListBySelector(ctx context.Context, request *common.Selector) (_ *common.RegistrationEntries, err error) {196 counter := telemetry_registrationapi.StartListEntriesCall(h.Metrics)197 telemetry_common.AddCallerID(counter, getCallerID(ctx))198 defer counter.Done(&err)199 log := h.Log.WithField(telemetry.Method, telemetry.ListRegistrationsBySelector)200 ds := h.getDataStore()201 req := &datastore.ListRegistrationEntriesRequest{202 BySelectors: &datastore.BySelectors{203 Selectors: []*common.Selector{request},204 },205 }206 resp, err := ds.ListRegistrationEntries(ctx, req)207 if err != nil {208 log.WithError(err).Error("Failed to list entries by selector")209 return nil, status.Errorf(codes.Internal, "error trying to list entries by selector: %v", err)210 }211 return &common.RegistrationEntries{212 Entries: resp.Entries,213 }, nil214}215//ListBySelectors returns all the Entries associated with the Selectors216func (h *Handler) ListBySelectors(ctx context.Context, request *common.Selectors) (_ *common.RegistrationEntries, err error) {217 counter := telemetry_registrationapi.StartListEntriesCall(h.Metrics)218 telemetry_common.AddCallerID(counter, getCallerID(ctx))219 defer counter.Done(&err)220 log := h.Log.WithField(telemetry.Method, telemetry.ListRegistrationsBySelectors)221 ds := h.getDataStore()222 req := &datastore.ListRegistrationEntriesRequest{223 BySelectors: &datastore.BySelectors{224 Selectors: request.Entries,225 },226 }227 resp, err := ds.ListRegistrationEntries(ctx, req)228 if err != nil {229 log.WithError(err).Error("Failed to list entries by selectors")230 return nil, status.Errorf(codes.Internal, "error trying to list entries by selectors: %v", err)231 }232 return &common.RegistrationEntries{233 Entries: resp.Entries,234 }, nil235}236//ListBySpiffeID returns all the Entries associated with the SPIFFE ID237func (h *Handler) ListBySpiffeID(ctx context.Context, request *registration.SpiffeID) (_ *common.RegistrationEntries, err error) {238 counter := telemetry_registrationapi.StartListEntriesCall(h.Metrics)239 telemetry_common.AddCallerID(counter, getCallerID(ctx))240 defer counter.Done(&err)241 log := h.Log.WithField(telemetry.Method, telemetry.ListRegistrationsBySPIFFEID)242 request.Id, err = idutil.NormalizeSpiffeID(request.Id, idutil.AllowAny())243 if err != nil {244 log.WithError(err).Error("Failed to normalize SPIFFE ID")245 return nil, status.Error(codes.InvalidArgument, err.Error())246 }247 ds := h.getDataStore()248 req := &datastore.ListRegistrationEntriesRequest{249 BySpiffeId: &wrappers.StringValue{250 Value: request.Id,251 },252 }253 resp, err := ds.ListRegistrationEntries(ctx, req)254 if err != nil {255 log.WithError(err).Error("Failed to list entries by SPIFFE ID")256 return nil, status.Errorf(codes.Internal, "error trying to list entries by SPIFFE ID: %v", err)257 }258 return &common.RegistrationEntries{259 Entries: resp.Entries,260 }, nil261}262//ListAllEntriesWithPages retrieves all registered entries with pagination.263func (h *Handler) ListAllEntriesWithPages(ctx context.Context, request *registration.ListAllEntriesRequest) (_ *registration.ListAllEntriesResponse, err error) {264 counter := telemetry_registrationapi.StartListEntriesCall(h.Metrics)265 telemetry_common.AddCallerID(counter, getCallerID(ctx))266 defer counter.Done(&err)267 log := h.Log.WithField(telemetry.Method, telemetry.ListAllEntriesWithPages)268 ds := h.getDataStore()269 var pageSize int32 = defaultListEntriesPageSize270 var token string271 if request.Pagination != nil {272 if request.Pagination.PageSize != 0 {273 pageSize = request.Pagination.PageSize274 }275 token = request.Pagination.Token276 }277 fetchResponse, err := ds.ListRegistrationEntries(ctx, &datastore.ListRegistrationEntriesRequest{278 Pagination: &datastore.Pagination{279 Token: token,280 PageSize: pageSize,281 },282 })283 if err != nil {284 log.WithError(err).Error("Error trying to fetch entries")285 return nil, status.Errorf(codes.Internal, "error trying to fetch entries: %v", err)286 }287 return ®istration.ListAllEntriesResponse{288 Entries: fetchResponse.Entries,289 Pagination: ®istration.Pagination{290 Token: fetchResponse.Pagination.Token,291 PageSize: fetchResponse.Pagination.PageSize,292 },293 }, nil294}295func (h *Handler) CreateFederatedBundle(ctx context.Context, request *registration.FederatedBundle) (_ *common.Empty, err error) {296 counter := telemetry_registrationapi.StartCreateFedBundleCall(h.Metrics)297 telemetry_common.AddCallerID(counter, getCallerID(ctx))298 defer counter.Done(&err)299 log := h.Log.WithField(telemetry.Method, telemetry.CreateFederatedBundle)300 bundle := request.Bundle301 if bundle == nil {302 log.Error("Bundle field is required")303 return nil, status.Error(codes.InvalidArgument, "bundle field is required")304 }305 bundle.TrustDomainId, err = idutil.NormalizeSpiffeID(bundle.TrustDomainId, idutil.AllowAnyTrustDomain())306 if err != nil {307 log.WithError(err).Error("Failed to normalize SPIFFE ID")308 return nil, status.Error(codes.InvalidArgument, err.Error())309 }310 if bundle.TrustDomainId == h.TrustDomain.String() {311 log.Error("Federated bundle id cannot match server trust domain")312 return nil, status.Error(codes.InvalidArgument, "federated bundle id cannot match server trust domain")313 }314 ds := h.getDataStore()315 if _, err := ds.CreateBundle(ctx, &datastore.CreateBundleRequest{316 Bundle: bundle,317 }); err != nil {318 log.WithError(err).Error("Failed to create bundle")319 return nil, status.Error(codes.Internal, err.Error())320 }321 return &common.Empty{}, nil322}323func (h *Handler) FetchFederatedBundle(ctx context.Context, request *registration.FederatedBundleID) (_ *registration.FederatedBundle, err error) {324 counter := telemetry_registrationapi.StartFetchFedBundleCall(h.Metrics)325 telemetry_common.AddCallerID(counter, getCallerID(ctx))326 defer counter.Done(&err)327 log := h.Log.WithField(telemetry.Method, telemetry.FetchFederatedBundle)328 request.Id, err = idutil.NormalizeSpiffeID(request.Id, idutil.AllowAnyTrustDomain())329 if err != nil {330 log.WithError(err).Error("Failed to normalize SPIFFE ID")331 return nil, status.Error(codes.InvalidArgument, err.Error())332 }333 if request.Id == h.TrustDomain.String() {334 log.Error("Federated bundle id cannot match server trust domain")335 return nil, status.Error(codes.InvalidArgument, "federated bundle id cannot match server trust domain")336 }337 ds := h.getDataStore()338 resp, err := ds.FetchBundle(ctx, &datastore.FetchBundleRequest{339 TrustDomainId: request.Id,340 })341 if err != nil {342 log.WithError(err).Error("Failed to fetch bundle")343 return nil, status.Error(codes.Internal, err.Error())344 }345 if resp.Bundle == nil {346 log.Error("Bundle not found")347 return nil, status.Error(codes.NotFound, "bundle not found")348 }349 return ®istration.FederatedBundle{350 Bundle: resp.Bundle,351 }, nil352}353func (h *Handler) ListFederatedBundles(request *common.Empty, stream registration.Registration_ListFederatedBundlesServer) (err error) {354 counter := telemetry_registrationapi.StartListFedBundlesCall(h.Metrics)355 telemetry_common.AddCallerID(counter, getCallerID(stream.Context()))356 defer counter.Done(&err)357 log := h.Log.WithField(telemetry.Method, telemetry.ListFederatedBundles)358 ds := h.getDataStore()359 resp, err := ds.ListBundles(stream.Context(), &datastore.ListBundlesRequest{})360 if err != nil {361 log.WithError(err).Error("Failed to list bundles")362 return status.Error(codes.Internal, err.Error())363 }364 for _, bundle := range resp.Bundles {365 if bundle.TrustDomainId == h.TrustDomain.String() {366 continue367 }368 if err := stream.Send(®istration.FederatedBundle{369 Bundle: bundle,370 }); err != nil {371 log.WithError(err).Error("Failed to send response over stream")372 return status.Error(codes.Internal, err.Error())373 }374 }375 return nil376}377func (h *Handler) UpdateFederatedBundle(ctx context.Context, request *registration.FederatedBundle) (_ *common.Empty, err error) {378 counter := telemetry_registrationapi.StartUpdateFedBundleCall(h.Metrics)379 telemetry_common.AddCallerID(counter, getCallerID(ctx))380 defer counter.Done(&err)381 log := h.Log.WithField(telemetry.Method, telemetry.UpdateFederatedBundle)382 bundle := request.Bundle383 if bundle == nil {384 log.Error("Bundle field is required")385 return nil, status.Error(codes.InvalidArgument, "bundle field is required")386 }387 bundle.TrustDomainId, err = idutil.NormalizeSpiffeID(bundle.TrustDomainId, idutil.AllowAnyTrustDomain())388 if err != nil {389 log.WithError(err).Error("Failed to normalize SPIFFE ID")390 return nil, status.Error(codes.InvalidArgument, err.Error())391 }392 if bundle.TrustDomainId == h.TrustDomain.String() {393 log.Error("Federated bundle ID cannot match server trust domain")394 return nil, status.Error(codes.InvalidArgument, "federated bundle id cannot match server trust domain")395 }396 ds := h.getDataStore()397 if _, err := ds.UpdateBundle(ctx, &datastore.UpdateBundleRequest{398 Bundle: bundle,399 }); err != nil {400 log.WithError(err).Error("Failed to update federated bundle")401 return nil, status.Error(codes.Internal, err.Error())402 }403 return &common.Empty{}, err404}405func (h *Handler) DeleteFederatedBundle(ctx context.Context, request *registration.DeleteFederatedBundleRequest) (_ *common.Empty, err error) {406 counter := telemetry_registrationapi.StartDeleteFedBundleCall(h.Metrics)407 telemetry_common.AddCallerID(counter, getCallerID(ctx))408 defer counter.Done(&err)409 log := h.Log.WithField(telemetry.Method, telemetry.DeleteFederatedBundle)410 request.Id, err = idutil.NormalizeSpiffeID(request.Id, idutil.AllowAnyTrustDomain())411 if err != nil {412 log.WithError(err).Error("Failed to normalize SPIFFE ID")413 return nil, status.Error(codes.InvalidArgument, err.Error())414 }415 if request.Id == h.TrustDomain.String() {416 log.Error("Federated bundle ID cannot match server trust domain")417 return nil, status.Error(codes.InvalidArgument, "federated bundle id cannot match server trust domain")418 }419 mode, err := convertDeleteBundleMode(request.Mode)420 if err != nil {421 log.WithError(err).Error("Unknown delete bundle mode in request")422 return nil, status.Error(codes.InvalidArgument, err.Error())423 }424 ds := h.getDataStore()425 if _, err := ds.DeleteBundle(ctx, &datastore.DeleteBundleRequest{426 TrustDomainId: request.Id,427 Mode: mode,428 }); err != nil {429 log.WithError(err).Error("Failed to delete federated bundle")430 return nil, status.Error(codes.Internal, err.Error())431 }432 return &common.Empty{}, nil433}434func (h *Handler) CreateJoinToken(ctx context.Context, request *registration.JoinToken) (_ *registration.JoinToken, err error) {435 counter := telemetry_registrationapi.StartCreateJoinTokenCall(h.Metrics)436 telemetry_common.AddCallerID(counter, getCallerID(ctx))437 defer counter.Done(&err)438 log := h.Log.WithField(telemetry.Method, telemetry.CreateJoinToken)439 if request.Ttl < 1 {440 log.Error("TTL is required")441 return nil, status.Error(codes.InvalidArgument, "ttl is required, you must provide one")442 }443 // Generate a token if one wasn't specified444 if request.Token == "" {445 u, err := uuid.NewV4()446 if err != nil {447 log.WithError(err).Error("Failed to generate UUID token")448 return nil, status.Errorf(codes.Internal, "error generating uuid token: %v", err)449 }450 request.Token = u.String()451 }452 ds := h.getDataStore()453 expiry := time.Now().Unix() + int64(request.Ttl)454 _, err = ds.CreateJoinToken(ctx, &datastore.CreateJoinTokenRequest{455 JoinToken: &datastore.JoinToken{456 Token: request.Token,457 Expiry: expiry,458 },459 })460 if err != nil {461 log.WithError(err).Error("Failed to register token")462 return nil, status.Errorf(codes.Internal, "Failed to register token: %v", err)463 }464 return request, nil465}466// FetchBundle retrieves the CA bundle.467func (h *Handler) FetchBundle(ctx context.Context, request *common.Empty) (_ *registration.Bundle, err error) {468 counter := telemetry_registrationapi.StartFetchBundleCall(h.Metrics)469 telemetry_common.AddCallerID(counter, getCallerID(ctx))470 defer counter.Done(&err)471 log := h.Log.WithField(telemetry.Method, telemetry.FetchBundle)472 ds := h.getDataStore()473 resp, err := ds.FetchBundle(ctx, &datastore.FetchBundleRequest{474 TrustDomainId: h.TrustDomain.String(),475 })476 if err != nil {477 log.WithError(err).Error("Failed to get bundle from datastore")478 return nil, status.Errorf(codes.Internal, "get bundle from datastore: %v", err)479 }480 if resp.Bundle == nil {481 log.Error("Bundle not found")482 return nil, status.Error(codes.NotFound, "bundle not found")483 }484 return ®istration.Bundle{485 Bundle: resp.Bundle,486 }, nil487}488//EvictAgent removes a node from the attested nodes store489func (h *Handler) EvictAgent(ctx context.Context, evictRequest *registration.EvictAgentRequest) (*registration.EvictAgentResponse, error) {490 spiffeID := evictRequest.GetSpiffeID()491 log := h.Log.WithFields(logrus.Fields{492 telemetry.Method: telemetry.EvictAgent,493 telemetry.SPIFFEID: spiffeID,494 })495 deletedNode, err := h.deleteAttestedNode(ctx, spiffeID)496 if err != nil {497 log.WithError(err).Warn("Failed to evict agent")498 return nil, err499 }500 log.Debug("Successfully evicted agent")501 return ®istration.EvictAgentResponse{502 Node: deletedNode,503 }, nil504}505//ListAgents returns the list of attested nodes506func (h *Handler) ListAgents(ctx context.Context, listReq *registration.ListAgentsRequest) (*registration.ListAgentsResponse, error) {507 log := h.Log.WithField(telemetry.Method, telemetry.ListAgents)508 ds := h.Catalog.GetDataStore()509 req := &datastore.ListAttestedNodesRequest{}510 resp, err := ds.ListAttestedNodes(ctx, req)511 if err != nil {512 log.WithError(err).Error("Failed to list attested nodes")513 return nil, err514 }515 return ®istration.ListAgentsResponse{Nodes: resp.Nodes}, nil516}517func (h *Handler) MintX509SVID(ctx context.Context, req *registration.MintX509SVIDRequest) (_ *registration.MintX509SVIDResponse, err error) {518 counter := telemetry_registrationapi.StartMintX509SVIDCall(h.Metrics)519 telemetry_common.AddCallerID(counter, getCallerID(ctx))520 defer counter.Done(&err)521 log := h.Log.WithField(telemetry.Method, telemetry.MintX509SVID)522 spiffeID, err := h.normalizeSPIFFEIDForMinting(req.SpiffeId)523 if err != nil {524 log.WithError(err).Error("Failed to normalize SPIFFE ID for minting")525 return nil, err526 }527 if len(req.Csr) == 0 {528 log.Error("Request missing CSR")529 return nil, status.Error(codes.InvalidArgument, "request missing CSR")530 }531 for _, dnsName := range req.DnsNames {532 if err := validateDNS(dnsName); err != nil {533 log.WithField(telemetry.DNSName, dnsName).Error("Invalid DNS name")534 return nil, status.Errorf(codes.InvalidArgument, "invalid DNS name: %v", err)535 }536 }537 csr, err := x509.ParseCertificateRequest(req.Csr)538 if err != nil {539 log.WithError(err).Error("Invalid CSR")540 return nil, status.Errorf(codes.InvalidArgument, "invalid CSR: %v", err)541 }542 if err := csr.CheckSignature(); err != nil {543 log.WithError(err).Error("Invalid CSR: signature verification failed")544 return nil, status.Errorf(codes.InvalidArgument, "invalid CSR: signature verify failed")545 }546 svid, err := h.ServerCA.SignX509SVID(ctx, ca.X509SVIDParams{547 SpiffeID: spiffeID,548 PublicKey: csr.PublicKey,549 TTL: time.Duration(req.Ttl) * time.Second,550 DNSList: req.DnsNames,551 })552 if err != nil {553 log.WithError(err).Error("Failed to sign X.509 SVID")554 return nil, status.Error(codes.Internal, err.Error())555 }556 resp, err := h.getDataStore().FetchBundle(ctx, &datastore.FetchBundleRequest{557 TrustDomainId: h.TrustDomain.String(),558 })559 if err != nil {560 log.WithError(err).Error("Failed to fetch bundle from datastore")561 return nil, status.Error(codes.Internal, err.Error())562 }563 if resp.Bundle == nil {564 log.Error("Bundle not found")565 return nil, status.Error(codes.FailedPrecondition, "bundle not found")566 }567 svidChain := make([][]byte, 0, len(svid))568 for _, cert := range svid {569 svidChain = append(svidChain, cert.Raw)570 }571 var rootCAs [][]byte572 for _, rootCA := range resp.Bundle.RootCas {573 rootCAs = append(rootCAs, rootCA.DerBytes)574 }575 return ®istration.MintX509SVIDResponse{576 SvidChain: svidChain,577 RootCas: rootCAs,578 }, nil579}580func (h *Handler) MintJWTSVID(ctx context.Context, req *registration.MintJWTSVIDRequest) (_ *registration.MintJWTSVIDResponse, err error) {581 counter := telemetry_registrationapi.StartMintJWTSVIDCall(h.Metrics)582 telemetry_common.AddCallerID(counter, getCallerID(ctx))583 defer counter.Done(&err)584 log := h.Log.WithField(telemetry.Method, telemetry.MintJWTSVID)585 spiffeID, err := h.normalizeSPIFFEIDForMinting(req.SpiffeId)586 if err != nil {587 log.WithError(err).Error("Failed to normalize SPIFFE ID for minting")588 return nil, err589 }590 if len(req.Audience) == 0 {591 log.Error("Request must specify at least one audience")592 return nil, status.Error(codes.InvalidArgument, "request must specify at least one audience")593 }594 token, err := h.ServerCA.SignJWTSVID(ctx, ca.JWTSVIDParams{595 SpiffeID: spiffeID,596 TTL: time.Duration(req.Ttl) * time.Second,597 Audience: req.Audience,598 })599 if err != nil {600 log.WithError(err).Error("Failed to sign JWT-SVID")601 return nil, status.Error(codes.Internal, err.Error())602 }603 return ®istration.MintJWTSVIDResponse{604 Token: token,605 }, nil606}607// GetNodeSelectors returns node (agent) selectors608func (h *Handler) GetNodeSelectors(ctx context.Context, req *registration.GetNodeSelectorsRequest) (*registration.GetNodeSelectorsResponse, error) {609 log := h.Log.WithField(telemetry.Method, telemetry.GetNodeSelectors)610 ds := h.Catalog.GetDataStore()611 r := &datastore.GetNodeSelectorsRequest{612 SpiffeId: req.SpiffeId,613 }614 resp, err := ds.GetNodeSelectors(ctx, r)615 if err != nil {616 log.WithError(err).Error("Failed to get node selectors")617 return nil, err618 }619 return ®istration.GetNodeSelectorsResponse{620 Selectors: ®istration.NodeSelectors{621 SpiffeId: resp.Selectors.SpiffeId,622 Selectors: resp.Selectors.Selectors,623 },624 }, nil625}626func (h *Handler) deleteAttestedNode(ctx context.Context, agentID string) (*common.AttestedNode, error) {627 if agentID == "" {628 return nil, errors.New("empty agent ID")629 }630 ds := h.Catalog.GetDataStore()631 req := &datastore.DeleteAttestedNodeRequest{632 SpiffeId: agentID,633 }634 resp, err := ds.DeleteAttestedNode(ctx, req)635 if err != nil {636 return nil, err637 }638 return resp.Node, nil639}640func (h *Handler) normalizeSPIFFEIDForMinting(spiffeID string) (string, error) {641 if spiffeID == "" {642 return "", status.Error(codes.InvalidArgument, "request missing SPIFFE ID")643 }644 spiffeID, err := idutil.NormalizeSpiffeID(spiffeID, idutil.AllowTrustDomainWorkload(h.TrustDomain.Host))645 if err != nil {646 return "", status.Errorf(codes.InvalidArgument, err.Error())647 }648 return spiffeID, nil649}650func (h *Handler) isEntryUnique(ctx context.Context, ds datastore.DataStore, entry *common.RegistrationEntry) (*common.RegistrationEntry, bool, error) {651 // First we get all the entries that matches the entry's spiffe id.652 req := &datastore.ListRegistrationEntriesRequest{653 BySpiffeId: &wrappers.StringValue{654 Value: entry.SpiffeId,655 },656 ByParentId: &wrappers.StringValue{657 Value: entry.ParentId,658 },659 BySelectors: &datastore.BySelectors{660 Match: datastore.BySelectors_MATCH_EXACT,661 Selectors: entry.Selectors,662 },663 }664 res, err := ds.ListRegistrationEntries(ctx, req)665 if err != nil {666 return nil, false, err667 }668 existing := new(common.RegistrationEntry)669 unique := len(res.Entries) == 0670 if !unique {671 existing = res.Entries[0]672 }673 return existing, unique, nil674}675func (h *Handler) getDataStore() datastore.DataStore {676 return h.Catalog.GetDataStore()677}678func (h *Handler) createRegistrationEntry(ctx context.Context, requestedEntry *common.RegistrationEntry) (entry *common.RegistrationEntry, preexisting bool, err error) {679 requestedEntry, err = h.prepareRegistrationEntry(requestedEntry, false)680 if err != nil {681 return nil, false, status.Error(codes.InvalidArgument, err.Error())682 }683 ds := h.getDataStore()684 existingEntry, unique, err := h.isEntryUnique(ctx, ds, requestedEntry)685 if err != nil {686 return nil, false, status.Errorf(codes.Internal, "error trying to create entry: %v", err)687 }688 if !unique {689 return existingEntry, true, nil690 }691 createResponse, err := ds.CreateRegistrationEntry(ctx,692 &datastore.CreateRegistrationEntryRequest{Entry: requestedEntry},693 )694 if err != nil {695 return nil, false, status.Errorf(codes.Internal, "error trying to create entry: %v", err)696 }697 return createResponse.Entry, false, nil698}699func (h *Handler) prepareRegistrationEntry(entry *common.RegistrationEntry, forUpdate bool) (*common.RegistrationEntry, error) {700 entry = cloneRegistrationEntry(entry)701 if forUpdate && entry.EntryId == "" {702 return nil, errors.New("missing registration entry id")703 }704 var err error705 for _, dns := range entry.DnsNames {706 err = validateDNS(dns)707 if err != nil {708 return nil, fmt.Errorf("dns name %v failed validation: %v", dns, err)709 }710 }711 entry.ParentId, err = idutil.NormalizeSpiffeID(entry.ParentId, idutil.AllowAnyInTrustDomain(h.TrustDomain.Host))712 if err != nil {713 return nil, err714 }715 // Validate Spiffe ID716 entry.SpiffeId, err = idutil.NormalizeSpiffeID(entry.SpiffeId, idutil.AllowTrustDomainWorkload(h.TrustDomain.Host))717 if err != nil {718 return nil, err719 }720 return entry, nil721}722func (h *Handler) AuthorizeCall(ctx context.Context, fullMethod string) (_ context.Context, err error) {723 // For the time being, authorization is not per-method. In other words, all or nothing.724 counter := telemetry_registrationapi.StartAuthorizeCall(h.Metrics, fullMethod)725 defer counter.Done(&err)726 log := h.Log.WithField(telemetry.Method, fullMethod)727 callerID, err := authorizeCaller(ctx, h.getDataStore())728 if err != nil {729 log.WithError(err).Error("Failed to authorize caller")730 return nil, err731 }732 if callerID != "" {733 ctx = withCallerID(ctx, callerID)734 }735 return ctx, nil736}737func cloneRegistrationEntry(entry *common.RegistrationEntry) *common.RegistrationEntry {738 return proto.Clone(entry).(*common.RegistrationEntry)739}740func convertDeleteBundleMode(in registration.DeleteFederatedBundleRequest_Mode) (datastore.DeleteBundleRequest_Mode, error) {741 switch in {742 case registration.DeleteFederatedBundleRequest_RESTRICT:743 return datastore.DeleteBundleRequest_RESTRICT, nil744 case registration.DeleteFederatedBundleRequest_DISSOCIATE:745 return datastore.DeleteBundleRequest_DISSOCIATE, nil746 case registration.DeleteFederatedBundleRequest_DELETE:747 return datastore.DeleteBundleRequest_DELETE, nil748 }749 return datastore.DeleteBundleRequest_RESTRICT, fmt.Errorf("unhandled delete mode %q", in)750}751func getSpiffeIDFromCert(cert *x509.Certificate) (string, error) {752 if len(cert.URIs) == 0 {753 return "", errors.New("no SPIFFE ID in certificate")754 }755 spiffeID, err := idutil.NormalizeSpiffeIDURL(cert.URIs[0], idutil.AllowAny())756 if err != nil {757 return "", err758 }759 return spiffeID.String(), nil760}761func authorizeCaller(ctx context.Context, ds datastore.DataStore) (spiffeID string, err error) {762 ctxPeer, ok := peer.FromContext(ctx)763 if !ok {764 return "", status.Error(codes.PermissionDenied, "no peer information for caller")765 }766 switch authInfo := ctxPeer.AuthInfo.(type) {767 case credentials.TLSInfo:768 // The caller came over TLS and must present an authorized SPIFFE ID769 if len(authInfo.State.VerifiedChains) == 0 {...
config_test.go
Source:config_test.go
1package agent2import (3 "fmt"4 "io/ioutil"5 "net"6 "os"7 "path/filepath"8 "reflect"9 "testing"10 "time"11 "github.com/hashicorp/consul/lib/freeport"12 "github.com/hashicorp/nomad/helper"13 "github.com/hashicorp/nomad/nomad/structs"14 "github.com/hashicorp/nomad/nomad/structs/config"15 "github.com/stretchr/testify/require"16)17var (18 // trueValue/falseValue are used to get a pointer to a boolean19 trueValue = true20 falseValue = false21)22func TestConfig_Merge(t *testing.T) {23 c0 := &Config{}24 c1 := &Config{25 Telemetry: &Telemetry{},26 Client: &ClientConfig{},27 Server: &ServerConfig{},28 ACL: &ACLConfig{},29 Ports: &Ports{},30 Addresses: &Addresses{},31 AdvertiseAddrs: &AdvertiseAddrs{},32 Vault: &config.VaultConfig{},33 Consul: &config.ConsulConfig{},34 Sentinel: &config.SentinelConfig{},35 Autopilot: &config.AutopilotConfig{},36 }37 c2 := &Config{38 Region: "global",39 Datacenter: "dc1",40 NodeName: "node1",41 DataDir: "/tmp/dir1",42 PluginDir: "/tmp/pluginDir1",43 LogLevel: "INFO",44 LogJson: false,45 EnableDebug: false,46 LeaveOnInt: false,47 LeaveOnTerm: false,48 EnableSyslog: false,49 SyslogFacility: "local0.info",50 DisableUpdateCheck: helper.BoolToPtr(false),51 DisableAnonymousSignature: false,52 BindAddr: "127.0.0.1",53 Telemetry: &Telemetry{54 StatsiteAddr: "127.0.0.1:8125",55 StatsdAddr: "127.0.0.1:8125",56 DataDogAddr: "127.0.0.1:8125",57 DataDogTags: []string{"cat1:tag1", "cat2:tag2"},58 PrometheusMetrics: true,59 DisableHostname: false,60 DisableTaggedMetrics: true,61 BackwardsCompatibleMetrics: true,62 CirconusAPIToken: "0",63 CirconusAPIApp: "nomadic",64 CirconusAPIURL: "http://api.circonus.com/v2",65 CirconusSubmissionInterval: "60s",66 CirconusCheckSubmissionURL: "https://someplace.com/metrics",67 CirconusCheckID: "0",68 CirconusCheckForceMetricActivation: "true",69 CirconusCheckInstanceID: "node1:nomadic",70 CirconusCheckSearchTag: "service:nomadic",71 CirconusCheckDisplayName: "node1:nomadic",72 CirconusCheckTags: "cat1:tag1,cat2:tag2",73 CirconusBrokerID: "0",74 CirconusBrokerSelectTag: "dc:dc1",75 PrefixFilter: []string{"filter1", "filter2"},76 },77 Client: &ClientConfig{78 Enabled: false,79 StateDir: "/tmp/state1",80 AllocDir: "/tmp/alloc1",81 NodeClass: "class1",82 Options: map[string]string{83 "foo": "bar",84 },85 NetworkSpeed: 100,86 CpuCompute: 100,87 MemoryMB: 100,88 MaxKillTimeout: "20s",89 ClientMaxPort: 19996,90 DisableRemoteExec: false,91 Reserved: &Resources{92 CPU: 10,93 MemoryMB: 10,94 DiskMB: 10,95 ReservedPorts: "1,10-30,55",96 },97 },98 Server: &ServerConfig{99 Enabled: false,100 AuthoritativeRegion: "global",101 BootstrapExpect: 1,102 DataDir: "/tmp/data1",103 ProtocolVersion: 1,104 RaftProtocol: 1,105 NumSchedulers: helper.IntToPtr(1),106 NodeGCThreshold: "1h",107 HeartbeatGrace: 30 * time.Second,108 MinHeartbeatTTL: 30 * time.Second,109 MaxHeartbeatsPerSecond: 30.0,110 RedundancyZone: "foo",111 UpgradeVersion: "foo",112 },113 ACL: &ACLConfig{114 Enabled: true,115 TokenTTL: 60 * time.Second,116 PolicyTTL: 60 * time.Second,117 ReplicationToken: "foo",118 },119 Ports: &Ports{120 HTTP: 4646,121 RPC: 4647,122 Serf: 4648,123 },124 Addresses: &Addresses{125 HTTP: "127.0.0.1",126 RPC: "127.0.0.1",127 Serf: "127.0.0.1",128 },129 AdvertiseAddrs: &AdvertiseAddrs{130 RPC: "127.0.0.1",131 Serf: "127.0.0.1",132 },133 HTTPAPIResponseHeaders: map[string]string{134 "Access-Control-Allow-Origin": "*",135 },136 Vault: &config.VaultConfig{137 Token: "1",138 AllowUnauthenticated: &falseValue,139 TaskTokenTTL: "1",140 Addr: "1",141 TLSCaFile: "1",142 TLSCaPath: "1",143 TLSCertFile: "1",144 TLSKeyFile: "1",145 TLSSkipVerify: &falseValue,146 TLSServerName: "1",147 },148 Consul: &config.ConsulConfig{149 ServerServiceName: "1",150 ClientServiceName: "1",151 AutoAdvertise: &falseValue,152 Addr: "1",153 Timeout: 1 * time.Second,154 Token: "1",155 Auth: "1",156 EnableSSL: &falseValue,157 VerifySSL: &falseValue,158 CAFile: "1",159 CertFile: "1",160 KeyFile: "1",161 ServerAutoJoin: &falseValue,162 ClientAutoJoin: &falseValue,163 ChecksUseAdvertise: &falseValue,164 },165 Autopilot: &config.AutopilotConfig{166 CleanupDeadServers: &falseValue,167 ServerStabilizationTime: 1 * time.Second,168 LastContactThreshold: 1 * time.Second,169 MaxTrailingLogs: 1,170 EnableRedundancyZones: &falseValue,171 DisableUpgradeMigration: &falseValue,172 EnableCustomUpgrades: &falseValue,173 },174 Plugins: []*config.PluginConfig{175 {176 Name: "docker",177 Args: []string{"foo"},178 Config: map[string]interface{}{179 "bar": 1,180 },181 },182 },183 }184 c3 := &Config{185 Region: "global",186 Datacenter: "dc2",187 NodeName: "node2",188 DataDir: "/tmp/dir2",189 PluginDir: "/tmp/pluginDir2",190 LogLevel: "DEBUG",191 LogJson: true,192 EnableDebug: true,193 LeaveOnInt: true,194 LeaveOnTerm: true,195 EnableSyslog: true,196 SyslogFacility: "local0.debug",197 DisableUpdateCheck: helper.BoolToPtr(true),198 DisableAnonymousSignature: true,199 BindAddr: "127.0.0.2",200 Telemetry: &Telemetry{201 StatsiteAddr: "127.0.0.2:8125",202 StatsdAddr: "127.0.0.2:8125",203 DataDogAddr: "127.0.0.1:8125",204 DataDogTags: []string{"cat1:tag1", "cat2:tag2"},205 PrometheusMetrics: true,206 DisableHostname: true,207 PublishNodeMetrics: true,208 PublishAllocationMetrics: true,209 DisableTaggedMetrics: true,210 BackwardsCompatibleMetrics: true,211 CirconusAPIToken: "1",212 CirconusAPIApp: "nomad",213 CirconusAPIURL: "https://api.circonus.com/v2",214 CirconusSubmissionInterval: "10s",215 CirconusCheckSubmissionURL: "https://example.com/metrics",216 CirconusCheckID: "1",217 CirconusCheckForceMetricActivation: "false",218 CirconusCheckInstanceID: "node2:nomad",219 CirconusCheckSearchTag: "service:nomad",220 CirconusCheckDisplayName: "node2:nomad",221 CirconusCheckTags: "cat1:tag1,cat2:tag2",222 CirconusBrokerID: "1",223 CirconusBrokerSelectTag: "dc:dc2",224 PrefixFilter: []string{"prefix1", "prefix2"},225 DisableDispatchedJobSummaryMetrics: true,226 FilterDefault: helper.BoolToPtr(false),227 },228 Client: &ClientConfig{229 Enabled: true,230 StateDir: "/tmp/state2",231 AllocDir: "/tmp/alloc2",232 NodeClass: "class2",233 Servers: []string{"server2"},234 Meta: map[string]string{235 "baz": "zip",236 },237 Options: map[string]string{238 "foo": "bar",239 "baz": "zip",240 },241 ChrootEnv: map[string]string{},242 ClientMaxPort: 20000,243 ClientMinPort: 22000,244 NetworkSpeed: 105,245 CpuCompute: 105,246 MemoryMB: 105,247 MaxKillTimeout: "50s",248 DisableRemoteExec: false,249 Reserved: &Resources{250 CPU: 15,251 MemoryMB: 15,252 DiskMB: 15,253 ReservedPorts: "2,10-30,55",254 },255 GCInterval: 6 * time.Second,256 GCParallelDestroys: 6,257 GCDiskUsageThreshold: 71,258 GCInodeUsageThreshold: 86,259 },260 Server: &ServerConfig{261 Enabled: true,262 AuthoritativeRegion: "global2",263 BootstrapExpect: 2,264 DataDir: "/tmp/data2",265 ProtocolVersion: 2,266 RaftProtocol: 2,267 NumSchedulers: helper.IntToPtr(2),268 EnabledSchedulers: []string{structs.JobTypeBatch},269 NodeGCThreshold: "12h",270 HeartbeatGrace: 2 * time.Minute,271 MinHeartbeatTTL: 2 * time.Minute,272 MaxHeartbeatsPerSecond: 200.0,273 RejoinAfterLeave: true,274 StartJoin: []string{"1.1.1.1"},275 RetryJoin: []string{"1.1.1.1"},276 RetryInterval: time.Second * 10,277 NonVotingServer: true,278 RedundancyZone: "bar",279 UpgradeVersion: "bar",280 },281 ACL: &ACLConfig{282 Enabled: true,283 TokenTTL: 20 * time.Second,284 PolicyTTL: 20 * time.Second,285 ReplicationToken: "foobar",286 },287 Ports: &Ports{288 HTTP: 20000,289 RPC: 21000,290 Serf: 22000,291 },292 Addresses: &Addresses{293 HTTP: "127.0.0.2",294 RPC: "127.0.0.2",295 Serf: "127.0.0.2",296 },297 AdvertiseAddrs: &AdvertiseAddrs{298 RPC: "127.0.0.2",299 Serf: "127.0.0.2",300 },301 HTTPAPIResponseHeaders: map[string]string{302 "Access-Control-Allow-Origin": "*",303 "Access-Control-Allow-Methods": "GET, POST, OPTIONS",304 },305 Vault: &config.VaultConfig{306 Token: "2",307 AllowUnauthenticated: &trueValue,308 TaskTokenTTL: "2",309 Addr: "2",310 TLSCaFile: "2",311 TLSCaPath: "2",312 TLSCertFile: "2",313 TLSKeyFile: "2",314 TLSSkipVerify: &trueValue,315 TLSServerName: "2",316 },317 Consul: &config.ConsulConfig{318 ServerServiceName: "2",319 ClientServiceName: "2",320 AutoAdvertise: &trueValue,321 Addr: "2",322 Timeout: 2 * time.Second,323 Token: "2",324 Auth: "2",325 EnableSSL: &trueValue,326 VerifySSL: &trueValue,327 CAFile: "2",328 CertFile: "2",329 KeyFile: "2",330 ServerAutoJoin: &trueValue,331 ClientAutoJoin: &trueValue,332 ChecksUseAdvertise: &trueValue,333 },334 Sentinel: &config.SentinelConfig{335 Imports: []*config.SentinelImport{336 {337 Name: "foo",338 Path: "foo",339 Args: []string{"a", "b", "c"},340 },341 },342 },343 Autopilot: &config.AutopilotConfig{344 CleanupDeadServers: &trueValue,345 ServerStabilizationTime: 2 * time.Second,346 LastContactThreshold: 2 * time.Second,347 MaxTrailingLogs: 2,348 EnableRedundancyZones: &trueValue,349 DisableUpgradeMigration: &trueValue,350 EnableCustomUpgrades: &trueValue,351 },352 Plugins: []*config.PluginConfig{353 {354 Name: "docker",355 Args: []string{"bam"},356 Config: map[string]interface{}{357 "baz": 2,358 },359 },360 {361 Name: "exec",362 Args: []string{"arg"},363 Config: map[string]interface{}{364 "config": true,365 },366 },367 },368 }369 result := c0.Merge(c1)370 result = result.Merge(c2)371 result = result.Merge(c3)372 if !reflect.DeepEqual(result, c3) {373 t.Fatalf("bad:\n%#v\n%#v", result, c3)374 }375}376func TestConfig_ParseConfigFile(t *testing.T) {377 // Fails if the file doesn't exist378 if _, err := ParseConfigFile("/unicorns/leprechauns"); err == nil {379 t.Fatalf("expected error, got nothing")380 }381 fh, err := ioutil.TempFile("", "nomad")382 if err != nil {383 t.Fatalf("err: %s", err)384 }385 defer os.RemoveAll(fh.Name())386 // Invalid content returns error387 if _, err := fh.WriteString("nope;!!!"); err != nil {388 t.Fatalf("err: %s", err)389 }390 if _, err := ParseConfigFile(fh.Name()); err == nil {391 t.Fatalf("expected load error, got nothing")392 }393 // Valid content parses successfully394 if err := fh.Truncate(0); err != nil {395 t.Fatalf("err: %s", err)396 }397 if _, err := fh.Seek(0, 0); err != nil {398 t.Fatalf("err: %s", err)399 }400 if _, err := fh.WriteString(`{"region":"west"}`); err != nil {401 t.Fatalf("err: %s", err)402 }403 config, err := ParseConfigFile(fh.Name())404 if err != nil {405 t.Fatalf("err: %s", err)406 }407 if config.Region != "west" {408 t.Fatalf("bad region: %q", config.Region)409 }410}411func TestConfig_LoadConfigDir(t *testing.T) {412 // Fails if the dir doesn't exist.413 if _, err := LoadConfigDir("/unicorns/leprechauns"); err == nil {414 t.Fatalf("expected error, got nothing")415 }416 dir, err := ioutil.TempDir("", "nomad")417 if err != nil {418 t.Fatalf("err: %s", err)419 }420 defer os.RemoveAll(dir)421 // Returns empty config on empty dir422 config, err := LoadConfig(dir)423 if err != nil {424 t.Fatalf("err: %s", err)425 }426 if config == nil {427 t.Fatalf("should not be nil")428 }429 file1 := filepath.Join(dir, "conf1.hcl")430 err = ioutil.WriteFile(file1, []byte(`{"region":"west"}`), 0600)431 if err != nil {432 t.Fatalf("err: %s", err)433 }434 file2 := filepath.Join(dir, "conf2.hcl")435 err = ioutil.WriteFile(file2, []byte(`{"datacenter":"sfo"}`), 0600)436 if err != nil {437 t.Fatalf("err: %s", err)438 }439 file3 := filepath.Join(dir, "conf3.hcl")440 err = ioutil.WriteFile(file3, []byte(`nope;!!!`), 0600)441 if err != nil {442 t.Fatalf("err: %s", err)443 }444 // Fails if we have a bad config file445 if _, err := LoadConfigDir(dir); err == nil {446 t.Fatalf("expected load error, got nothing")447 }448 if err := os.Remove(file3); err != nil {449 t.Fatalf("err: %s", err)450 }451 // Works if configs are valid452 config, err = LoadConfigDir(dir)453 if err != nil {454 t.Fatalf("err: %s", err)455 }456 if config.Region != "west" || config.Datacenter != "sfo" {457 t.Fatalf("bad: %#v", config)458 }459}460func TestConfig_LoadConfig(t *testing.T) {461 // Fails if the target doesn't exist462 if _, err := LoadConfig("/unicorns/leprechauns"); err == nil {463 t.Fatalf("expected error, got nothing")464 }465 fh, err := ioutil.TempFile("", "nomad")466 if err != nil {467 t.Fatalf("err: %s", err)468 }469 defer os.Remove(fh.Name())470 if _, err := fh.WriteString(`{"region":"west"}`); err != nil {471 t.Fatalf("err: %s", err)472 }473 // Works on a config file474 config, err := LoadConfig(fh.Name())475 if err != nil {476 t.Fatalf("err: %s", err)477 }478 if config.Region != "west" {479 t.Fatalf("bad: %#v", config)480 }481 expectedConfigFiles := []string{fh.Name()}482 if !reflect.DeepEqual(config.Files, expectedConfigFiles) {483 t.Errorf("Loaded configs don't match\nExpected\n%+vGot\n%+v\n",484 expectedConfigFiles, config.Files)485 }486 dir, err := ioutil.TempDir("", "nomad")487 if err != nil {488 t.Fatalf("err: %s", err)489 }490 defer os.RemoveAll(dir)491 file1 := filepath.Join(dir, "config1.hcl")492 err = ioutil.WriteFile(file1, []byte(`{"datacenter":"sfo"}`), 0600)493 if err != nil {494 t.Fatalf("err: %s", err)495 }496 // Works on config dir497 config, err = LoadConfig(dir)498 if err != nil {499 t.Fatalf("err: %s", err)500 }501 if config.Datacenter != "sfo" {502 t.Fatalf("bad: %#v", config)503 }504 expectedConfigFiles = []string{file1}505 if !reflect.DeepEqual(config.Files, expectedConfigFiles) {506 t.Errorf("Loaded configs don't match\nExpected\n%+vGot\n%+v\n",507 expectedConfigFiles, config.Files)508 }509}510func TestConfig_LoadConfigsFileOrder(t *testing.T) {511 config1, err := LoadConfigDir("test-resources/etcnomad")512 if err != nil {513 t.Fatalf("Failed to load config: %s", err)514 }515 config2, err := LoadConfig("test-resources/myconf")516 if err != nil {517 t.Fatalf("Failed to load config: %s", err)518 }519 expected := []string{520 // filepath.FromSlash changes these to backslash \ on Windows521 filepath.FromSlash("test-resources/etcnomad/common.hcl"),522 filepath.FromSlash("test-resources/etcnomad/server.json"),523 filepath.FromSlash("test-resources/myconf"),524 }525 config := config1.Merge(config2)526 if !reflect.DeepEqual(config.Files, expected) {527 t.Errorf("Loaded configs don't match\nwant: %+v\n got: %+v\n",528 expected, config.Files)529 }530}531func TestConfig_Listener(t *testing.T) {532 config := DefaultConfig()533 // Fails on invalid input534 if ln, err := config.Listener("tcp", "nope", 8080); err == nil {535 ln.Close()536 t.Fatalf("expected addr error")537 }538 if ln, err := config.Listener("nope", "127.0.0.1", 8080); err == nil {539 ln.Close()540 t.Fatalf("expected protocol err")541 }542 if ln, err := config.Listener("tcp", "127.0.0.1", -1); err == nil {543 ln.Close()544 t.Fatalf("expected port error")545 }546 // Works with valid inputs547 ports := freeport.GetT(t, 2)548 ln, err := config.Listener("tcp", "127.0.0.1", ports[0])549 if err != nil {550 t.Fatalf("err: %s", err)551 }552 ln.Close()553 if net := ln.Addr().Network(); net != "tcp" {554 t.Fatalf("expected tcp, got: %q", net)555 }556 want := fmt.Sprintf("127.0.0.1:%d", ports[0])557 if addr := ln.Addr().String(); addr != want {558 t.Fatalf("expected %q, got: %q", want, addr)559 }560 // Falls back to default bind address if non provided561 config.BindAddr = "0.0.0.0"562 ln, err = config.Listener("tcp4", "", ports[1])563 if err != nil {564 t.Fatalf("err: %s", err)565 }566 ln.Close()567 want = fmt.Sprintf("0.0.0.0:%d", ports[1])568 if addr := ln.Addr().String(); addr != want {569 t.Fatalf("expected %q, got: %q", want, addr)570 }571}572// TestConfig_normalizeAddrs_DevMode asserts that normalizeAddrs allows573// advertising localhost in dev mode.574func TestConfig_normalizeAddrs_DevMode(t *testing.T) {575 // allow to advertise 127.0.0.1 if dev-mode is enabled576 c := &Config{577 BindAddr: "127.0.0.1",578 Ports: &Ports{579 HTTP: 4646,580 RPC: 4647,581 Serf: 4648,582 },583 Addresses: &Addresses{},584 AdvertiseAddrs: &AdvertiseAddrs{},585 DevMode: true,586 }587 if err := c.normalizeAddrs(); err != nil {588 t.Fatalf("unable to normalize addresses: %s", err)589 }590 if c.BindAddr != "127.0.0.1" {591 t.Fatalf("expected BindAddr 127.0.0.1, got %s", c.BindAddr)592 }593 if c.normalizedAddrs.HTTP != "127.0.0.1:4646" {594 t.Fatalf("expected HTTP address 127.0.0.1:4646, got %s", c.normalizedAddrs.HTTP)595 }596 if c.normalizedAddrs.RPC != "127.0.0.1:4647" {597 t.Fatalf("expected RPC address 127.0.0.1:4647, got %s", c.normalizedAddrs.RPC)598 }599 if c.normalizedAddrs.Serf != "127.0.0.1:4648" {600 t.Fatalf("expected Serf address 127.0.0.1:4648, got %s", c.normalizedAddrs.Serf)601 }602 if c.AdvertiseAddrs.HTTP != "127.0.0.1:4646" {603 t.Fatalf("expected HTTP advertise address 127.0.0.1:4646, got %s", c.AdvertiseAddrs.HTTP)604 }605 if c.AdvertiseAddrs.RPC != "127.0.0.1:4647" {606 t.Fatalf("expected RPC advertise address 127.0.0.1:4647, got %s", c.AdvertiseAddrs.RPC)607 }608 // Client mode, no Serf address defined609 if c.AdvertiseAddrs.Serf != "" {610 t.Fatalf("expected unset Serf advertise address, got %s", c.AdvertiseAddrs.Serf)611 }612}613// TestConfig_normalizeAddrs_NoAdvertise asserts that normalizeAddrs will614// fail if no valid advertise address available in non-dev mode.615func TestConfig_normalizeAddrs_NoAdvertise(t *testing.T) {616 c := &Config{617 BindAddr: "127.0.0.1",618 Ports: &Ports{619 HTTP: 4646,620 RPC: 4647,621 Serf: 4648,622 },623 Addresses: &Addresses{},624 AdvertiseAddrs: &AdvertiseAddrs{},625 DevMode: false,626 }627 if err := c.normalizeAddrs(); err == nil {628 t.Fatalf("expected an error when no valid advertise address is available")629 }630 if c.AdvertiseAddrs.HTTP == "127.0.0.1:4646" {631 t.Fatalf("expected non-localhost HTTP advertise address, got %s", c.AdvertiseAddrs.HTTP)632 }633 if c.AdvertiseAddrs.RPC == "127.0.0.1:4647" {634 t.Fatalf("expected non-localhost RPC advertise address, got %s", c.AdvertiseAddrs.RPC)635 }636 if c.AdvertiseAddrs.Serf == "127.0.0.1:4648" {637 t.Fatalf("expected non-localhost Serf advertise address, got %s", c.AdvertiseAddrs.Serf)638 }639}640// TestConfig_normalizeAddrs_AdvertiseLocalhost asserts localhost can be641// advertised if it's explicitly set in the config.642func TestConfig_normalizeAddrs_AdvertiseLocalhost(t *testing.T) {643 c := &Config{644 BindAddr: "127.0.0.1",645 Ports: &Ports{646 HTTP: 4646,647 RPC: 4647,648 Serf: 4648,649 },650 Addresses: &Addresses{},651 AdvertiseAddrs: &AdvertiseAddrs{652 HTTP: "127.0.0.1",653 RPC: "127.0.0.1",654 Serf: "127.0.0.1",655 },656 DevMode: false,657 Server: &ServerConfig{Enabled: true},658 }659 if err := c.normalizeAddrs(); err != nil {660 t.Fatalf("unexpected error when manually setting bind mode: %v", err)661 }662 if c.AdvertiseAddrs.HTTP != "127.0.0.1:4646" {663 t.Errorf("expected localhost HTTP advertise address, got %s", c.AdvertiseAddrs.HTTP)664 }665 if c.AdvertiseAddrs.RPC != "127.0.0.1:4647" {666 t.Errorf("expected localhost RPC advertise address, got %s", c.AdvertiseAddrs.RPC)667 }668 if c.AdvertiseAddrs.Serf != "127.0.0.1:4648" {669 t.Errorf("expected localhost Serf advertise address, got %s", c.AdvertiseAddrs.Serf)670 }671}672// TestConfig_normalizeAddrs_IPv6Loopback asserts that an IPv6 loopback address673// is normalized properly. See #2739674func TestConfig_normalizeAddrs_IPv6Loopback(t *testing.T) {675 c := &Config{676 BindAddr: "::1",677 Ports: &Ports{678 HTTP: 4646,679 RPC: 4647,680 },681 Addresses: &Addresses{},682 AdvertiseAddrs: &AdvertiseAddrs{683 HTTP: "::1",684 RPC: "::1",685 },686 DevMode: false,687 }688 if err := c.normalizeAddrs(); err != nil {689 t.Fatalf("unexpected error when manually setting bind mode: %v", err)690 }691 if c.Addresses.HTTP != "::1" {692 t.Errorf("expected ::1 HTTP address, got %s", c.Addresses.HTTP)693 }694 if c.Addresses.RPC != "::1" {695 t.Errorf("expected ::1 RPC address, got %s", c.Addresses.RPC)696 }697 if c.AdvertiseAddrs.HTTP != "[::1]:4646" {698 t.Errorf("expected [::1] HTTP advertise address, got %s", c.AdvertiseAddrs.HTTP)699 }700 if c.AdvertiseAddrs.RPC != "[::1]:4647" {701 t.Errorf("expected [::1] RPC advertise address, got %s", c.AdvertiseAddrs.RPC)702 }703}704func TestConfig_normalizeAddrs(t *testing.T) {705 c := &Config{706 BindAddr: "169.254.1.5",707 Ports: &Ports{708 HTTP: 4646,709 RPC: 4647,710 Serf: 4648,711 },712 Addresses: &Addresses{713 HTTP: "169.254.1.10",714 },715 AdvertiseAddrs: &AdvertiseAddrs{716 RPC: "169.254.1.40",717 },718 Server: &ServerConfig{719 Enabled: true,720 },721 }722 if err := c.normalizeAddrs(); err != nil {723 t.Fatalf("unable to normalize addresses: %s", err)724 }725 if c.BindAddr != "169.254.1.5" {726 t.Fatalf("expected BindAddr 169.254.1.5, got %s", c.BindAddr)727 }728 if c.AdvertiseAddrs.HTTP != "169.254.1.10:4646" {729 t.Fatalf("expected HTTP advertise address 169.254.1.10:4646, got %s", c.AdvertiseAddrs.HTTP)730 }731 if c.AdvertiseAddrs.RPC != "169.254.1.40:4647" {732 t.Fatalf("expected RPC advertise address 169.254.1.40:4647, got %s", c.AdvertiseAddrs.RPC)733 }734 if c.AdvertiseAddrs.Serf != "169.254.1.5:4648" {735 t.Fatalf("expected Serf advertise address 169.254.1.5:4648, got %s", c.AdvertiseAddrs.Serf)736 }737 c = &Config{738 BindAddr: "{{ GetPrivateIP }}",739 Ports: &Ports{740 HTTP: 4646,741 RPC: 4647,742 Serf: 4648,743 },744 Addresses: &Addresses{},745 AdvertiseAddrs: &AdvertiseAddrs{746 RPC: "{{ GetPrivateIP }}",747 },748 Server: &ServerConfig{749 Enabled: true,750 },751 }752 if err := c.normalizeAddrs(); err != nil {753 t.Fatalf("unable to normalize addresses: %s", err)754 }755 exp := net.JoinHostPort(c.BindAddr, "4646")756 if c.AdvertiseAddrs.HTTP != exp {757 t.Fatalf("expected HTTP advertise address %s, got %s", exp, c.AdvertiseAddrs.HTTP)758 }759 exp = net.JoinHostPort(c.BindAddr, "4647")760 if c.AdvertiseAddrs.RPC != exp {761 t.Fatalf("expected RPC advertise address %s, got %s", exp, c.AdvertiseAddrs.RPC)762 }763 exp = net.JoinHostPort(c.BindAddr, "4648")764 if c.AdvertiseAddrs.Serf != exp {765 t.Fatalf("expected Serf advertise address %s, got %s", exp, c.AdvertiseAddrs.Serf)766 }767 // allow to advertise 127.0.0.1 in non-dev mode, if explicitly configured to do so768 c = &Config{769 BindAddr: "127.0.0.1",770 Ports: &Ports{771 HTTP: 4646,772 RPC: 4647,773 Serf: 4648,774 },775 Addresses: &Addresses{},776 AdvertiseAddrs: &AdvertiseAddrs{777 HTTP: "127.0.0.1:4646",778 RPC: "127.0.0.1:4647",779 Serf: "127.0.0.1:4648",780 },781 DevMode: false,782 Server: &ServerConfig{783 Enabled: true,784 },785 }786 if err := c.normalizeAddrs(); err != nil {787 t.Fatalf("unable to normalize addresses: %s", err)788 }789 if c.AdvertiseAddrs.HTTP != "127.0.0.1:4646" {790 t.Fatalf("expected HTTP advertise address 127.0.0.1:4646, got %s", c.AdvertiseAddrs.HTTP)791 }792 if c.AdvertiseAddrs.RPC != "127.0.0.1:4647" {793 t.Fatalf("expected RPC advertise address 127.0.0.1:4647, got %s", c.AdvertiseAddrs.RPC)794 }795 if c.AdvertiseAddrs.RPC != "127.0.0.1:4647" {796 t.Fatalf("expected RPC advertise address 127.0.0.1:4647, got %s", c.AdvertiseAddrs.RPC)797 }798}799func TestIsMissingPort(t *testing.T) {800 _, _, err := net.SplitHostPort("localhost")801 if missing := isMissingPort(err); !missing {802 t.Errorf("expected missing port error, but got %v", err)803 }804 _, _, err = net.SplitHostPort("localhost:9000")805 if missing := isMissingPort(err); missing {806 t.Errorf("expected no error, but got %v", err)807 }808}809func TestMergeServerJoin(t *testing.T) {810 require := require.New(t)811 {812 retryJoin := []string{"127.0.0.1", "127.0.0.2"}813 startJoin := []string{"127.0.0.1", "127.0.0.2"}814 retryMaxAttempts := 1815 retryInterval := time.Duration(0)816 a := &ServerJoin{817 RetryJoin: retryJoin,818 StartJoin: startJoin,819 RetryMaxAttempts: retryMaxAttempts,820 RetryInterval: time.Duration(retryInterval),821 }822 b := &ServerJoin{}823 result := a.Merge(b)824 require.Equal(result.RetryJoin, retryJoin)825 require.Equal(result.StartJoin, startJoin)826 require.Equal(result.RetryMaxAttempts, retryMaxAttempts)827 require.Equal(result.RetryInterval, retryInterval)828 }829 {830 retryJoin := []string{"127.0.0.1", "127.0.0.2"}831 startJoin := []string{"127.0.0.1", "127.0.0.2"}832 retryMaxAttempts := 1833 retryInterval := time.Duration(0)834 a := &ServerJoin{}835 b := &ServerJoin{836 RetryJoin: retryJoin,837 StartJoin: startJoin,838 RetryMaxAttempts: retryMaxAttempts,839 RetryInterval: time.Duration(retryInterval),840 }841 result := a.Merge(b)842 require.Equal(result.RetryJoin, retryJoin)843 require.Equal(result.StartJoin, startJoin)844 require.Equal(result.RetryMaxAttempts, retryMaxAttempts)845 require.Equal(result.RetryInterval, retryInterval)846 }847 {848 retryJoin := []string{"127.0.0.1", "127.0.0.2"}849 startJoin := []string{"127.0.0.1", "127.0.0.2"}850 retryMaxAttempts := 1851 retryInterval := time.Duration(0)852 var a *ServerJoin853 b := &ServerJoin{854 RetryJoin: retryJoin,855 StartJoin: startJoin,856 RetryMaxAttempts: retryMaxAttempts,857 RetryInterval: time.Duration(retryInterval),858 }859 result := a.Merge(b)860 require.Equal(result.RetryJoin, retryJoin)861 require.Equal(result.StartJoin, startJoin)862 require.Equal(result.RetryMaxAttempts, retryMaxAttempts)863 require.Equal(result.RetryInterval, retryInterval)864 }865 {866 retryJoin := []string{"127.0.0.1", "127.0.0.2"}867 startJoin := []string{"127.0.0.1", "127.0.0.2"}868 retryMaxAttempts := 1869 retryInterval := time.Duration(0)870 a := &ServerJoin{871 RetryJoin: retryJoin,872 StartJoin: startJoin,873 RetryMaxAttempts: retryMaxAttempts,874 RetryInterval: time.Duration(retryInterval),875 }876 var b *ServerJoin877 result := a.Merge(b)878 require.Equal(result.RetryJoin, retryJoin)879 require.Equal(result.StartJoin, startJoin)880 require.Equal(result.RetryMaxAttempts, retryMaxAttempts)881 require.Equal(result.RetryInterval, retryInterval)882 }883 {884 retryJoin := []string{"127.0.0.1", "127.0.0.2"}885 startJoin := []string{"127.0.0.1", "127.0.0.2"}886 retryMaxAttempts := 1887 retryInterval := time.Duration(0)888 a := &ServerJoin{889 RetryJoin: retryJoin,890 StartJoin: startJoin,891 }892 b := &ServerJoin{893 RetryMaxAttempts: retryMaxAttempts,894 RetryInterval: time.Duration(retryInterval),895 }896 result := a.Merge(b)897 require.Equal(result.RetryJoin, retryJoin)898 require.Equal(result.StartJoin, startJoin)899 require.Equal(result.RetryMaxAttempts, retryMaxAttempts)900 require.Equal(result.RetryInterval, retryInterval)901 }902}903func TestTelemetry_PrefixFilters(t *testing.T) {904 t.Parallel()905 cases := []struct {906 in []string907 expAllow []string908 expBlock []string909 expErr bool910 }{911 {912 in: []string{"+foo"},913 expAllow: []string{"foo"},914 },915 {916 in: []string{"-foo"},917 expBlock: []string{"foo"},918 },919 {920 in: []string{"+a.b.c", "-x.y.z"},921 expAllow: []string{"a.b.c"},922 expBlock: []string{"x.y.z"},923 },924 {925 in: []string{"+foo", "bad", "-bar"},926 expErr: true,927 },928 }929 for i, c := range cases {930 t.Run(fmt.Sprintf("PrefixCase%d", i), func(t *testing.T) {931 require := require.New(t)932 tel := &Telemetry{933 PrefixFilter: c.in,934 }935 allow, block, err := tel.PrefixFilters()936 require.Exactly(c.expAllow, allow)937 require.Exactly(c.expBlock, block)938 require.Equal(c.expErr, err != nil)939 })940 }941}942func TestTelemetry_Parse(t *testing.T) {943 require := require.New(t)944 dir, err := ioutil.TempDir("", "nomad")945 require.NoError(err)946 defer os.RemoveAll(dir)947 file1 := filepath.Join(dir, "config1.hcl")948 err = ioutil.WriteFile(file1, []byte(`telemetry{949 prefix_filter = ["+nomad.raft"]950 filter_default = false951 disable_dispatched_job_summary_metrics = true952 }`), 0600)953 require.NoError(err)954 // Works on config dir955 config, err := LoadConfig(dir)956 require.NoError(err)957 require.False(*config.Telemetry.FilterDefault)958 require.Exactly([]string{"+nomad.raft"}, config.Telemetry.PrefixFilter)959 require.True(config.Telemetry.DisableDispatchedJobSummaryMetrics)960}...
msg_server.go
Source:msg_server.go
...45 }46 }47 // Combine names, normalize, and check for existing record48 n := fmt.Sprintf("%s.%s", msg.Record.Name, msg.Parent.Name)49 name, err := s.Keeper.Normalize(ctx, n)50 if err != nil {51 ctx.Logger().Error("invalid name", "name", name)52 return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())53 }54 if s.Keeper.NameExists(ctx, name) {55 ctx.Logger().Error("name already bound", "name", name)56 return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, types.ErrNameAlreadyBound.Error())57 }58 // Bind name to address59 address, err := sdk.AccAddressFromBech32(msg.Record.Address)60 if err != nil {61 ctx.Logger().Error("invalid address", "err", err)62 return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())63 }64 if err := s.Keeper.SetNameRecord(ctx, name, address, msg.Record.Restricted); err != nil {65 ctx.Logger().Error("unable to bind name", "err", err)66 return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())67 }68 // key: modulename+name+bind69 defer func() {70 telemetry.IncrCounterWithLabels(71 []string{types.ModuleName, "name", "bind"},72 1,73 []metrics.Label{telemetry.NewLabel("name", name), telemetry.NewLabel("address", msg.Record.Address)},74 )75 }()76 ctx.EventManager().EmitEvent(77 sdk.NewEvent(78 types.EventTypeNameBound,79 sdk.NewAttribute(types.KeyAttributeAddress, msg.Record.Address),80 sdk.NewAttribute(types.KeyAttributeName, msg.Record.Name),81 ),82 )83 return &types.MsgBindNameResponse{}, nil84}85// DeleteName unbinds a name from an address86func (s msgServer) DeleteName(goCtx context.Context, msg *types.MsgDeleteNameRequest) (*types.MsgDeleteNameResponse, error) {87 ctx := sdk.UnwrapSDKContext(goCtx)88 // Validate89 if err := msg.ValidateBasic(); err != nil {90 ctx.Logger().Error("unable to validate message", "err", err)91 return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())92 }93 // Normalize94 name, err := s.Keeper.Normalize(ctx, msg.Record.Name)95 if err != nil {96 ctx.Logger().Error("invalid name", "err", err)97 return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())98 }99 // Parse address100 address, err := sdk.AccAddressFromBech32(msg.Record.Address)101 if err != nil {102 ctx.Logger().Error("invalid address", "err", err)103 return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, err.Error())104 }105 // Ensure the name exists106 if !s.Keeper.NameExists(ctx, name) {107 ctx.Logger().Error("invalid name", "name", name)108 return nil, sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "name does not exist")...
Normalize
Using AI Code Generation
1import (2func main() {3 config, err := edgegrid.Init("~/.edgerc", "default")4 if err != nil {5 fmt.Println(err)6 }7 telemetry.Init(config)8 query := telemetry.NewDataQuery()9 query.AddMetric("http-requests")10 query.AddDimension("status")11 query.AddDimension("requestUri")12 query.AddDimension("responseCode")13 query.AddDimension("responseCodeClass")14 query.AddDimension("datacenter")15 query.AddDimension("host")16 query.AddDimension("clientCountry")17 query.AddDimension("clientIpClass")18 query.AddDimension("clientIp")19 query.AddDimension("clientRequestHost")20 query.AddDimension("clientRequestMethod")21 query.AddDimension("clientRequestProtocol")22 query.AddDimension("clientRequestUri")23 query.AddDimension("clientRequestUriScheme")24 query.AddDimension("clientSslProtocol")25 query.AddDimension("clientSslCipher")26 query.AddDimension("clientSslClientAuth")27 query.AddDimension("clientSslClientAuthIssuer")28 query.AddDimension("clientSslClientAuthSerial")29 query.AddDimension("clientSslClientAuthSubject")30 query.AddDimension("clientSslClientAuthSubjectCommonName")31 query.AddDimension("clientSslClientAuthSubjectCountry")32 query.AddDimension("clientSslClientAuthSubjectLocality")33 query.AddDimension("clientSslClientAuthSubjectOrganization")34 query.AddDimension("clientSslClientAuthSubjectOrganizationalUnit")35 query.AddDimension("clientSslClientAuthSubjectState")36 query.AddDimension("clientSslClientAuthVersion")37 query.AddDimension("serverSslProtocol")38 query.AddDimension("serverSslCipher")39 query.AddDimension("serverSslSessionId")40 query.AddDimension("serverSslSessionTicket")41 query.AddDimension("serverSslSessionTicketAge")42 query.AddDimension("serverSslSessionTicketAgeNew")43 query.AddDimension("serverSslSessionTicketKey")44 query.AddDimension("serverSslSessionTicketKeySize")45 query.AddDimension("serverSslSessionTicketLifetime")46 query.AddDimension("serverSslSessionTicketLifetimeNew")47 query.AddDimension("serverSslSessionTicketRetransmit")48 query.AddDimension("serverSslSessionTicketSize")49 query.AddDimension("server
Normalize
Using AI Code Generation
1import (2var log = logger.GetLogger("normalize-function")3type Normalize struct {4}5func init() {6 function.Register(&Normalize{})7}8func (s *Normalize) Name() string {9}10func (s *Normalize) Sig() (paramTypes []data.Type, isVariadic bool) {11 return []data.Type{data.TypeAny, data.TypeAny, data.TypeAny}, false12}13func (s *Normalize) Eval(params ...interface{}) (interface{}, error) {14}15import (16var log = logger.GetLogger("normalize-function")17type Normalize struct {18}19func init() {20 function.Register(&Normalize{})21}22func (s *Normalize) Name() string {23}24func (s *Normalize) Sig() (paramTypes []data.Type, isVariadic bool) {25 return []data.Type{data.TypeAny, data.TypeAny, data.TypeAny}, false26}27func (s *Normalize) Eval(params ...interface{}) (interface{}, error) {28 input1 := params[0].(float64)29 input2 := params[1].(float64)30 input3 := params[2].(float64)31 log.Debugf("Input1 is [%s]", input1)32 log.Debugf("Input2
Normalize
Using AI Code Generation
1import telemetry.*;2public class Normalize {3 public static void main(String[] args) {4 Telemetry telemetry = new Telemetry();5 telemetry.setSpeed(100);6 telemetry.setDistance(100);7 telemetry.setFuel(100);8 telemetry.setTemperature(100);9 telemetry.setPressure(100);10 telemetry.setRpm(100);11 telemetry.setTireWear(100);12 telemetry.normalize();13 System.out.println("Normalized Speed: " + telemetry.getSpeed());14 System.out.println("Normalized Distance: " + telemetry.getDistance());15 System.out.println("Normalized Fuel: " + telemetry.getFuel());16 System.out.println("Normalized Temperature: " + telemetry.getTemperature());17 System.out.println("Normalized Pressure: " + telemetry.getPressure());18 System.out.println("Normalized RPM: " + telemetry.getRpm());19 System.out.println("Normalized Tire Wear: " + telemetry.getTireWear());20 }21}22import telemetry.*;23public class Normalize {24 public static void main(String[] args) {25 Telemetry telemetry = new Telemetry();26 telemetry.setSpeed(200);27 telemetry.setDistance(200);28 telemetry.setFuel(200);29 telemetry.setTemperature(200);30 telemetry.setPressure(200);31 telemetry.setRpm(200);32 telemetry.setTireWear(200);33 telemetry.normalize();34 System.out.println("Normalized Speed: " + telemetry.getSpeed());35 System.out.println("Normalized Distance: " + telemetry.getDistance());36 System.out.println("Normalized Fuel: " + telemetry.getFuel());37 System.out.println("Normalized Temperature: " + telemetry.getTemperature());38 System.out.println("Normalized Pressure: " + telemetry.getPressure());39 System.out.println("Normalized RPM: " + telemetry.getRpm());40 System.out.println("Normalized Tire Wear: " + telemetry.getTireWear());41 }42}
Normalize
Using AI Code Generation
1import (2func main() {3 t.Normalize()4 fmt.Println(t)5}6import (7func main() {8 t.Normalize()9 fmt.Println(t)10}11I have a function that returns a function. I'm trying to call the function that is returned by the function. I'm getting an error that says: "cannot call non-function t (type func() telemetry.Telemetry)". What am I doing wrong?12import (13func main() {14 t.Normalize()15 fmt.Println(t)16}17type Telemetry struct {18}19func (t Telemetry) Normalize() {20}21func NewTelemetry() func() Telemetry {22 return func() Telemetry {23 return Telemetry{}24 }25}26I have a function that returns a function. I'm trying to call the function that is returned by the function. I'm getting an error that says: "cannot call non-function t (type func() telemetry.Telemetry)". What am I doing wrong?27import (28func main() {29 t.Normalize()30 fmt.Println(t)31}
Normalize
Using AI Code Generation
1import (2func main() {3 client := telemetry.NewClient("your-api-key")4 if err != nil {5 fmt.Println(err)6 } else {7 fmt.Println(normalized)8 }9}10import (11func main() {12 client := telemetry.NewClient("your-api-key")13 if err != nil {14 fmt.Println(err)15 } else {16 fmt.Println(normalized)17 }18}19import (20func main() {21 client := telemetry.NewClient("your-api-key")22 if err != nil {23 fmt.Println(err)24 } else {25 fmt.Println(normalized)26 }27}28import (29func main() {30 client := telemetry.NewClient("your-api-key")31 if err != nil {32 fmt.Println(err)33 } else {34 fmt.Println(normalized)35 }36}37import (38func main() {39 client := telemetry.NewClient("your-api-key")40 if err != nil {41 fmt.Println(err)42 } else {43 fmt.Println(normalized)44 }45}46import (
Normalize
Using AI Code Generation
1import (2func main() {3 tel := telemetry.NewTelemetry()4 tel.Set("bytes.received", 1000)5 tel.Set("bytes.sent", 1000)6 tel.Set("messages.received", 1000)7 tel.Set("messages.sent", 1000)8 tel.Normalize()9 fmt.Println(tel.Get("bytes.received"))10 fmt.Println(tel.Get("bytes.sent"))11 fmt.Println(tel.Get("messages.received"))12 fmt.Println(tel.Get("messages.sent"))13}14import (15func main() {16 tel := telemetry.NewTelemetry()17 tel.Set("bytes.received", 1000)18 tel.Set("bytes.sent", 1000)19 tel.Set("messages.received", 1000)20 tel.Set("messages.sent", 1000)21 tel.Normalize()22 fmt.Println(tel.Get("bytes.received"))23 fmt.Println(tel.Get("bytes.sent"))24 fmt.Println(tel.Get("messages.received"))25 fmt.Println(tel.Get("messages.sent"))26}
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!