"}},"componentScriptGroups({\"componentId\":\"custom.widget.Beta_Footer\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"component({\"componentId\":\"custom.widget.Tag_Manager_Helper\"})":{"__typename":"Component","render({\"context\":{\"component\":{\"entities\":[],\"props\":{}},\"page\":{\"entities\":[],\"name\":\"TagPage\",\"props\":{},\"url\":\"https://community.f5.com/tag/python\"}}})":{"__typename":"ComponentRenderResult","html":" "}},"componentScriptGroups({\"componentId\":\"custom.widget.Tag_Manager_Helper\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"component({\"componentId\":\"custom.widget.Consent_Blackbar\"})":{"__typename":"Component","render({\"context\":{\"component\":{\"entities\":[],\"props\":{}},\"page\":{\"entities\":[],\"name\":\"TagPage\",\"props\":{},\"url\":\"https://community.f5.com/tag/python\"}}})":{"__typename":"ComponentRenderResult","html":""}},"componentScriptGroups({\"componentId\":\"custom.widget.Consent_Blackbar\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/community/NavbarDropdownToggle\"]})":[{"__ref":"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageListTabs\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageListTabs-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageView/MessageViewInline\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageView/MessageViewInline-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/Pager/PagerLoadMore\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/Pager/PagerLoadMore-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/customComponent/CustomComponent\"]})":[{"__ref":"CachedAsset:text:en_US-components/customComponent/CustomComponent-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/OverflowNav\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/OverflowNav-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserLink\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserLink-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageSubject\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageSubject-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageBody\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageBody-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageTime\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageTime-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeIcon\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageUnreadCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageUnreadCount-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageViewCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageViewCount-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/kudos/KudosCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/kudos/KudosCount-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageRepliesCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageRepliesCount-1744046271000"}],"cachedText({\"lastModified\":\"1744046271000\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1744046271000"}]},"Theme:customTheme1":{"__typename":"Theme","id":"customTheme1"},"User:user:-1":{"__typename":"User","id":"user:-1","uid":-1,"login":"Anonymous","email":"","avatar":null,"rank":null,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":"ANONYMOUS","registrationTime":null,"confirmEmailStatus":false,"registrationAccessLevel":"VIEW","ssoRegistrationFields":[]},"ssoId":null,"profileSettings":{"__typename":"ProfileSettings","dateDisplayStyle":{"__typename":"InheritableStringSettingWithPossibleValues","key":"layout.friendly_dates_enabled","value":"false","localValue":"true","possibleValues":["true","false"]},"dateDisplayFormat":{"__typename":"InheritableStringSetting","key":"layout.format_pattern_date","value":"dd-MMM-yyyy","localValue":"MM-dd-yyyy"},"language":{"__typename":"InheritableStringSettingWithPossibleValues","key":"profile.language","value":"en-US","localValue":null,"possibleValues":["en-US","de-DE"]},"repliesSortOrder":{"__typename":"InheritableStringSettingWithPossibleValues","key":"config.user_replies_sort_order","value":"DEFAULT","localValue":"DEFAULT","possibleValues":["DEFAULT","LIKES","PUBLISH_TIME","REVERSE_PUBLISH_TIME"]}},"deleted":false},"CachedAsset:pages-1746693049844":{"__typename":"CachedAsset","id":"pages-1746693049844","value":[{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.MvpProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/mvp-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogViewAllPostsPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId/all-posts/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CasePortalPage","type":"CASE_PORTAL","urlPath":"/caseportal","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CreateGroupHubPage","type":"GROUP_HUB","urlPath":"/groups/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CaseViewPage","type":"CASE_DETAILS","urlPath":"/case/:caseId/:caseNumber","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"InboxPage","type":"COMMUNITY","urlPath":"/inbox","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.AdvocacyProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/advocacy-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.NonCustomer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/non-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HelpFAQPage","type":"COMMUNITY","urlPath":"/help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Customer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaMessagePage","type":"IDEA_POST","urlPath":"/idea/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaViewAllIdeasPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/all-ideas/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"LoginPage","type":"USER","urlPath":"/signin","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogPostPage","type":"BLOG","urlPath":"/category/:categoryId/blogs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetInvolved","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.Learn","type":"COMMUNITY","urlPath":"/c/how-do-i/learn","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1739501996000,"localOverride":null,"page":{"id":"Test","type":"CUSTOM","urlPath":"/custom-test-2","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ThemeEditorPage","type":"COMMUNITY","urlPath":"/designer/themes","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbViewAllArticlesPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId/all-articles/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OccasionEditPage","type":"EVENT","urlPath":"/event/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OAuthAuthorizationAllowPage","type":"USER","urlPath":"/auth/authorize/allow","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"PageEditorPage","type":"COMMUNITY","urlPath":"/designer/pages","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"PostPage","type":"COMMUNITY","urlPath":"/category/:categoryId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumBoardPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbBoardPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"EventPostPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"UserBadgesPage","type":"COMMUNITY","urlPath":"/users/:login/:userId/badges","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"GroupHubMembershipAction","type":"GROUP_HUB","urlPath":"/membership/join/:nodeId/:membershipType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"MaintenancePage","type":"COMMUNITY","urlPath":"/maintenance","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaReplyPage","type":"IDEA_REPLY","urlPath":"/idea/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"UserSettingsPage","type":"USER","urlPath":"/mysettings/:userSettingsTab","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"GroupHubsPage","type":"GROUP_HUB","urlPath":"/groups","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumPostPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OccasionRsvpActionPage","type":"OCCASION","urlPath":"/event/:boardId/:messageSubject/:messageId/rsvp/:responseType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"VerifyUserEmailPage","type":"USER","urlPath":"/verifyemail/:userId/:verifyEmailToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"AllOccasionsPage","type":"OCCASION","urlPath":"/category/:categoryId/events/:boardId/all-events/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"EventBoardPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbReplyPage","type":"TKB_REPLY","urlPath":"/kb/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaBoardPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CommunityGuideLinesPage","type":"COMMUNITY","urlPath":"/communityguidelines","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CaseCreatePage","type":"SALESFORCE_CASE_CREATION","urlPath":"/caseportal/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbEditPage","type":"TKB","urlPath":"/kb/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForgotPasswordPage","type":"USER","urlPath":"/forgotpassword","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaEditPage","type":"IDEA","urlPath":"/idea/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TagPage","type":"COMMUNITY","urlPath":"/tag/:tagName","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogBoardPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OccasionMessagePage","type":"OCCASION_TOPIC","urlPath":"/event/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ManageContentPage","type":"COMMUNITY","urlPath":"/managecontent","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ClosedMembershipNodeNonMembersPage","type":"GROUP_HUB","urlPath":"/closedgroup/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.Community","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/community","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CommunityPage","type":"COMMUNITY","urlPath":"/","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.ContributeCode","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/contribute-code","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumMessagePage","type":"FORUM_TOPIC","urlPath":"/discussions/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaPostPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogMessagePage","type":"BLOG_ARTICLE","urlPath":"/blog/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"RegistrationPage","type":"USER","urlPath":"/register","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"EditGroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumEditPage","type":"FORUM","urlPath":"/discussions/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ResetPasswordPage","type":"USER","urlPath":"/resetpassword/:userId/:resetPasswordToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbMessagePage","type":"TKB_ARTICLE","urlPath":"/kb/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.Learn.AboutIrules","type":"COMMUNITY","urlPath":"/c/how-do-i/learn/about-irules","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogEditPage","type":"BLOG","urlPath":"/blog/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Support","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-support","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ManageUsersPage","type":"USER","urlPath":"/users/manage/:tab?/:manageUsersTab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumReplyPage","type":"FORUM_REPLY","urlPath":"/discussions/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"PrivacyPolicyPage","type":"COMMUNITY","urlPath":"/privacypolicy","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"NotificationPage","type":"COMMUNITY","urlPath":"/notifications","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"UserPage","type":"USER","urlPath":"/users/:login/:userId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HealthCheckPage","type":"COMMUNITY","urlPath":"/health","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OccasionReplyPage","type":"OCCASION_REPLY","urlPath":"/event/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ManageMembersPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/manage/:tab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"SearchResultsPage","type":"COMMUNITY","urlPath":"/search","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogReplyPage","type":"BLOG_REPLY","urlPath":"/blog/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"GroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TermsOfServicePage","type":"COMMUNITY","urlPath":"/termsofservice","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.SecurityIncident","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/security-incident","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CategoryPage","type":"CATEGORY","urlPath":"/category/:categoryId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumViewAllTopicsPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/all-topics/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbPostPage","type":"TKB","urlPath":"/category/:categoryId/kbs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"GroupHubPostPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI","type":"COMMUNITY","urlPath":"/c/how-do-i","__typename":"PageDescriptor"},"__typename":"PageResource"}],"localOverride":false},"CachedAsset:text:en_US-components/context/AppContext/AppContextProvider-0":{"__typename":"CachedAsset","id":"text:en_US-components/context/AppContext/AppContextProvider-0","value":{"noCommunity":"Cannot find community","noUser":"Cannot find current user","noNode":"Cannot find node with id {nodeId}","noMessage":"Cannot find message with id {messageId}","userBanned":"We're sorry, but you have been banned from using this site.","userBannedReason":"You have been banned for the following reason: {reason}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-0":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-0","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:theme:customTheme1-1746691843538":{"__typename":"CachedAsset","id":"theme:customTheme1-1746691843538","value":{"id":"customTheme1","animation":{"fast":"150ms","normal":"250ms","slow":"500ms","slowest":"750ms","function":"cubic-bezier(0.07, 0.91, 0.51, 1)","__typename":"AnimationThemeSettings"},"avatar":{"borderRadius":"50%","collections":["custom"],"__typename":"AvatarThemeSettings"},"basics":{"browserIcon":{"imageAssetName":"JimmyPackets-512-1702592938213.png","imageLastModified":"1702592945815","__typename":"ThemeAsset"},"customerLogo":{"imageAssetName":"f5_logo_fix-1704824537976.svg","imageLastModified":"1704824540697","__typename":"ThemeAsset"},"maximumWidthOfPageContent":"1600px","oneColumnNarrowWidth":"800px","gridGutterWidthMd":"30px","gridGutterWidthXs":"10px","pageWidthStyle":"WIDTH_OF_PAGE_CONTENT","__typename":"BasicsThemeSettings"},"buttons":{"borderRadiusSm":"5px","borderRadius":"5px","borderRadiusLg":"5px","paddingY":"5px","paddingYLg":"7px","paddingYHero":"var(--lia-bs-btn-padding-y-lg)","paddingX":"12px","paddingXLg":"14px","paddingXHero":"42px","fontStyle":"NORMAL","fontWeight":"400","textTransform":"NONE","disabledOpacity":0.5,"primaryTextColor":"var(--lia-bs-white)","primaryTextHoverColor":"var(--lia-bs-white)","primaryTextActiveColor":"var(--lia-bs-white)","primaryBgColor":"var(--lia-bs-primary)","primaryBgHoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.85))","primaryBgActiveColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.7))","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","primaryBorderActive":"1px solid transparent","primaryBorderFocus":"1px solid var(--lia-bs-white)","primaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","secondaryTextColor":"var(--lia-bs-gray-900)","secondaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","secondaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","secondaryBgColor":"var(--lia-bs-gray-400)","secondaryBgHoverColor":"hsl(var(--lia-bs-gray-400-h), var(--lia-bs-gray-400-s), calc(var(--lia-bs-gray-400-l) * 0.96))","secondaryBgActiveColor":"hsl(var(--lia-bs-gray-400-h), var(--lia-bs-gray-400-s), calc(var(--lia-bs-gray-400-l) * 0.92))","secondaryBorder":"1px solid transparent","secondaryBorderHover":"1px solid transparent","secondaryBorderActive":"1px solid transparent","secondaryBorderFocus":"1px solid transparent","secondaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","tertiaryTextColor":"var(--lia-bs-gray-900)","tertiaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","tertiaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","tertiaryBgColor":"transparent","tertiaryBgHoverColor":"transparent","tertiaryBgActiveColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.04)","tertiaryBorder":"1px solid transparent","tertiaryBorderHover":"1px solid hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","tertiaryBorderActive":"1px solid transparent","tertiaryBorderFocus":"1px solid transparent","tertiaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","destructiveTextColor":"var(--lia-bs-danger)","destructiveTextHoverColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.95))","destructiveTextActiveColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.9))","destructiveBgColor":"var(--lia-bs-gray-300)","destructiveBgHoverColor":"hsl(var(--lia-bs-gray-300-h), var(--lia-bs-gray-300-s), calc(var(--lia-bs-gray-300-l) * 0.96))","destructiveBgActiveColor":"hsl(var(--lia-bs-gray-300-h), var(--lia-bs-gray-300-s), calc(var(--lia-bs-gray-300-l) * 0.92))","destructiveBorder":"1px solid transparent","destructiveBorderHover":"1px solid transparent","destructiveBorderActive":"1px solid transparent","destructiveBorderFocus":"1px solid transparent","destructiveBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","__typename":"ButtonsThemeSettings"},"border":{"color":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","mainContent":"NONE","sideContent":"NONE","radiusSm":"3px","radius":"5px","radiusLg":"9px","radius50":"100vw","__typename":"BorderThemeSettings"},"boxShadow":{"xs":"0 0 0 1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.08), 0 3px 0 -1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.08)","sm":"0 2px 4px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.06)","md":"0 5px 15px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.15)","lg":"0 10px 30px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.15)","__typename":"BoxShadowThemeSettings"},"cards":{"bgColor":"var(--lia-panel-bg-color)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":"var(--lia-box-shadow-xs)","__typename":"CardsThemeSettings"},"chip":{"maxWidth":"300px","height":"30px","__typename":"ChipThemeSettings"},"coreTypes":{"defaultMessageLinkColor":"var(--lia-bs-primary)","defaultMessageLinkDecoration":"none","defaultMessageLinkFontStyle":"NORMAL","defaultMessageLinkFontWeight":"400","defaultMessageFontStyle":"NORMAL","defaultMessageFontWeight":"400","defaultMessageFontFamily":"var(--lia-bs-font-family-base)","forumColor":"#0C5C8D","forumFontFamily":"var(--lia-bs-font-family-base)","forumFontWeight":"var(--lia-default-message-font-weight)","forumLineHeight":"var(--lia-bs-line-height-base)","forumFontStyle":"var(--lia-default-message-font-style)","forumMessageLinkColor":"var(--lia-default-message-link-color)","forumMessageLinkDecoration":"var(--lia-default-message-link-decoration)","forumMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","forumMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","forumSolvedColor":"#62C026","blogColor":"#730015","blogFontFamily":"var(--lia-bs-font-family-base)","blogFontWeight":"var(--lia-default-message-font-weight)","blogLineHeight":"1.75","blogFontStyle":"var(--lia-default-message-font-style)","blogMessageLinkColor":"var(--lia-default-message-link-color)","blogMessageLinkDecoration":"var(--lia-default-message-link-decoration)","blogMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","blogMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","tkbColor":"#C20025","tkbFontFamily":"var(--lia-bs-font-family-base)","tkbFontWeight":"var(--lia-default-message-font-weight)","tkbLineHeight":"1.75","tkbFontStyle":"var(--lia-default-message-font-style)","tkbMessageLinkColor":"var(--lia-default-message-link-color)","tkbMessageLinkDecoration":"var(--lia-default-message-link-decoration)","tkbMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","tkbMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaColor":"#4099E2","qandaFontFamily":"var(--lia-bs-font-family-base)","qandaFontWeight":"var(--lia-default-message-font-weight)","qandaLineHeight":"var(--lia-bs-line-height-base)","qandaFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkColor":"var(--lia-default-message-link-color)","qandaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","qandaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaSolvedColor":"#3FA023","ideaColor":"#F3704B","ideaFontFamily":"var(--lia-bs-font-family-base)","ideaFontWeight":"var(--lia-default-message-font-weight)","ideaLineHeight":"var(--lia-bs-line-height-base)","ideaFontStyle":"var(--lia-default-message-font-style)","ideaMessageLinkColor":"var(--lia-default-message-link-color)","ideaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","ideaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","ideaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","contestColor":"#FCC845","contestFontFamily":"var(--lia-bs-font-family-base)","contestFontWeight":"var(--lia-default-message-font-weight)","contestLineHeight":"var(--lia-bs-line-height-base)","contestFontStyle":"var(--lia-default-message-link-font-style)","contestMessageLinkColor":"var(--lia-default-message-link-color)","contestMessageLinkDecoration":"var(--lia-default-message-link-decoration)","contestMessageLinkFontStyle":"ITALIC","contestMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","occasionColor":"#EE4B5B","occasionFontFamily":"var(--lia-bs-font-family-base)","occasionFontWeight":"var(--lia-default-message-font-weight)","occasionLineHeight":"var(--lia-bs-line-height-base)","occasionFontStyle":"var(--lia-default-message-font-style)","occasionMessageLinkColor":"var(--lia-default-message-link-color)","occasionMessageLinkDecoration":"var(--lia-default-message-link-decoration)","occasionMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","occasionMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","grouphubColor":"#491B62","categoryColor":"#949494","communityColor":"#FFFFFF","productColor":"#949494","__typename":"CoreTypesThemeSettings"},"colors":{"black":"#000000","white":"#FFFFFF","gray100":"#F7F7F7","gray200":"#F7F7F7","gray300":"#E8E8E8","gray400":"#D9D9D9","gray500":"#CCCCCC","gray600":"#949494","gray700":"#707070","gray800":"#545454","gray900":"#333333","dark":"#545454","light":"#F7F7F7","primary":"#0C5C8D","secondary":"#333333","bodyText":"#222222","bodyBg":"#F5F5F5","info":"#1D9CD3","success":"#62C026","warning":"#FFD651","danger":"#C20025","alertSystem":"#FF6600","textMuted":"#707070","highlight":"#FFFCAD","outline":"var(--lia-bs-primary)","custom":["#C20025","#081B85","#009639","#B3C6D7","#7CC0EB","#F29A36"],"__typename":"ColorsThemeSettings"},"divider":{"size":"3px","marginLeft":"4px","marginRight":"4px","borderRadius":"50%","bgColor":"var(--lia-bs-gray-600)","bgColorActive":"var(--lia-bs-gray-600)","__typename":"DividerThemeSettings"},"dropdown":{"fontSize":"var(--lia-bs-font-size-sm)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius-sm)","dividerBg":"var(--lia-bs-gray-300)","itemPaddingY":"5px","itemPaddingX":"20px","headerColor":"var(--lia-bs-gray-700)","__typename":"DropdownThemeSettings"},"email":{"link":{"color":"#0069D4","hoverColor":"#0061c2","decoration":"none","hoverDecoration":"underline","__typename":"EmailLinkSettings"},"border":{"color":"#e4e4e4","__typename":"EmailBorderSettings"},"buttons":{"borderRadiusLg":"5px","paddingXLg":"16px","paddingYLg":"7px","fontWeight":"700","primaryTextColor":"#ffffff","primaryTextHoverColor":"#ffffff","primaryBgColor":"#0069D4","primaryBgHoverColor":"#005cb8","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","__typename":"EmailButtonsSettings"},"panel":{"borderRadius":"5px","borderColor":"#e4e4e4","__typename":"EmailPanelSettings"},"__typename":"EmailThemeSettings"},"emoji":{"skinToneDefault":"#ffcd43","skinToneLight":"#fae3c5","skinToneMediumLight":"#e2cfa5","skinToneMedium":"#daa478","skinToneMediumDark":"#a78058","skinToneDark":"#5e4d43","__typename":"EmojiThemeSettings"},"heading":{"color":"var(--lia-bs-body-color)","fontFamily":"Inter","fontStyle":"NORMAL","fontWeight":"600","h1FontSize":"30px","h2FontSize":"25px","h3FontSize":"20px","h4FontSize":"18px","h5FontSize":"16px","h6FontSize":"16px","lineHeight":"1.2","subHeaderFontSize":"11px","subHeaderFontWeight":"500","h1LetterSpacing":"normal","h2LetterSpacing":"normal","h3LetterSpacing":"normal","h4LetterSpacing":"normal","h5LetterSpacing":"normal","h6LetterSpacing":"normal","subHeaderLetterSpacing":"2px","h1FontWeight":"var(--lia-bs-headings-font-weight)","h2FontWeight":"var(--lia-bs-headings-font-weight)","h3FontWeight":"var(--lia-bs-headings-font-weight)","h4FontWeight":"var(--lia-bs-headings-font-weight)","h5FontWeight":"var(--lia-bs-headings-font-weight)","h6FontWeight":"var(--lia-bs-headings-font-weight)","__typename":"HeadingThemeSettings"},"icons":{"size10":"10px","size12":"12px","size14":"14px","size16":"16px","size20":"20px","size24":"24px","size30":"30px","size40":"40px","size50":"50px","size60":"60px","size80":"80px","size120":"120px","size160":"160px","__typename":"IconsThemeSettings"},"imagePreview":{"bgColor":"var(--lia-bs-gray-900)","titleColor":"var(--lia-bs-white)","controlColor":"var(--lia-bs-white)","controlBgColor":"var(--lia-bs-gray-800)","__typename":"ImagePreviewThemeSettings"},"input":{"borderColor":"var(--lia-bs-gray-600)","disabledColor":"var(--lia-bs-gray-600)","focusBorderColor":"var(--lia-bs-primary)","labelMarginBottom":"10px","btnFontSize":"var(--lia-bs-font-size-sm)","focusBoxShadow":"0 0 0 3px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","checkLabelMarginBottom":"2px","checkboxBorderRadius":"3px","borderRadiusSm":"var(--lia-bs-border-radius-sm)","borderRadius":"var(--lia-bs-border-radius)","borderRadiusLg":"var(--lia-bs-border-radius-lg)","formTextMarginTop":"4px","textAreaBorderRadius":"var(--lia-bs-border-radius)","activeFillColor":"var(--lia-bs-primary)","__typename":"InputThemeSettings"},"loading":{"dotDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.2)","dotLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.5)","barDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.06)","barLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.4)","__typename":"LoadingThemeSettings"},"link":{"color":"var(--lia-bs-primary)","hoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) - 10%))","decoration":"none","hoverDecoration":"underline","__typename":"LinkThemeSettings"},"listGroup":{"itemPaddingY":"15px","itemPaddingX":"15px","borderColor":"var(--lia-bs-gray-300)","__typename":"ListGroupThemeSettings"},"modal":{"contentTextColor":"var(--lia-bs-body-color)","contentBg":"var(--lia-bs-white)","backgroundBg":"var(--lia-bs-black)","smSize":"440px","mdSize":"760px","lgSize":"1080px","backdropOpacity":0.3,"contentBoxShadowXs":"var(--lia-bs-box-shadow-sm)","contentBoxShadow":"var(--lia-bs-box-shadow)","headerFontWeight":"700","__typename":"ModalThemeSettings"},"navbar":{"position":"FIXED","background":{"attachment":null,"clip":null,"color":"var(--lia-bs-white)","imageAssetName":null,"imageLastModified":"0","origin":null,"position":"CENTER_CENTER","repeat":"NO_REPEAT","size":"COVER","__typename":"BackgroundProps"},"backgroundOpacity":0.8,"paddingTop":"15px","paddingBottom":"15px","borderBottom":"1px solid var(--lia-bs-border-color)","boxShadow":"var(--lia-bs-box-shadow-sm)","brandMarginRight":"30px","brandMarginRightSm":"10px","brandLogoHeight":"30px","linkGap":"10px","linkJustifyContent":"flex-start","linkPaddingY":"5px","linkPaddingX":"10px","linkDropdownPaddingY":"9px","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkColor":"var(--lia-bs-body-color)","linkHoverColor":"var(--lia-bs-primary)","linkFontSize":"var(--lia-bs-font-size-sm)","linkFontStyle":"NORMAL","linkFontWeight":"400","linkTextTransform":"NONE","linkLetterSpacing":"normal","linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkBgColor":"transparent","linkBgHoverColor":"transparent","linkBorder":"none","linkBorderHover":"none","linkBoxShadow":"none","linkBoxShadowHover":"none","linkTextBorderBottom":"none","linkTextBorderBottomHover":"none","dropdownPaddingTop":"10px","dropdownPaddingBottom":"15px","dropdownPaddingX":"10px","dropdownMenuOffset":"2px","dropdownDividerMarginTop":"10px","dropdownDividerMarginBottom":"10px","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","controllerIconColor":"var(--lia-bs-body-color)","controllerIconHoverColor":"var(--lia-bs-body-color)","controllerTextColor":"var(--lia-nav-controller-icon-color)","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","controllerHighlightColor":"hsla(30, 100%, 50%)","controllerHighlightTextColor":"var(--lia-yiq-light)","controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerColor":"var(--lia-nav-controller-icon-color)","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","hamburgerBgColor":"transparent","hamburgerBgHoverColor":"transparent","hamburgerBorder":"none","hamburgerBorderHover":"none","collapseMenuMarginLeft":"20px","collapseMenuDividerBg":"var(--lia-nav-link-color)","collapseMenuDividerOpacity":0.16,"__typename":"NavbarThemeSettings"},"pager":{"textColor":"var(--lia-bs-link-color)","textFontWeight":"var(--lia-font-weight-md)","textFontSize":"var(--lia-bs-font-size-sm)","__typename":"PagerThemeSettings"},"panel":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-bs-border-radius)","borderColor":"var(--lia-bs-border-color)","boxShadow":"none","__typename":"PanelThemeSettings"},"popover":{"arrowHeight":"8px","arrowWidth":"16px","maxWidth":"300px","minWidth":"100px","headerBg":"var(--lia-bs-white)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius)","boxShadow":"0 0.5rem 1rem hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.15)","__typename":"PopoverThemeSettings"},"prism":{"color":"#000000","bgColor":"#f5f2f0","fontFamily":"var(--font-family-monospace)","fontSize":"var(--lia-bs-font-size-base)","fontWeightBold":"var(--lia-bs-font-weight-bold)","fontStyleItalic":"italic","tabSize":2,"highlightColor":"#b3d4fc","commentColor":"#62707e","punctuationColor":"#6f6f6f","namespaceOpacity":"0.7","propColor":"#990055","selectorColor":"#517a00","operatorColor":"#906736","operatorBgColor":"hsla(0, 0%, 100%, 0.5)","keywordColor":"#0076a9","functionColor":"#d3284b","variableColor":"#c14700","__typename":"PrismThemeSettings"},"rte":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":" var(--lia-panel-box-shadow)","customColor1":"#bfedd2","customColor2":"#fbeeb8","customColor3":"#f8cac6","customColor4":"#eccafa","customColor5":"#c2e0f4","customColor6":"#2dc26b","customColor7":"#f1c40f","customColor8":"#e03e2d","customColor9":"#b96ad9","customColor10":"#3598db","customColor11":"#169179","customColor12":"#e67e23","customColor13":"#ba372a","customColor14":"#843fa1","customColor15":"#236fa1","customColor16":"#ecf0f1","customColor17":"#ced4d9","customColor18":"#95a5a6","customColor19":"#7e8c8d","customColor20":"#34495e","customColor21":"#000000","customColor22":"#ffffff","defaultMessageHeaderMarginTop":"14px","defaultMessageHeaderMarginBottom":"10px","defaultMessageItemMarginTop":"0","defaultMessageItemMarginBottom":"10px","diffAddedColor":"hsla(170, 53%, 51%, 0.4)","diffChangedColor":"hsla(43, 97%, 63%, 0.4)","diffNoneColor":"hsla(0, 0%, 80%, 0.4)","diffRemovedColor":"hsla(9, 74%, 47%, 0.4)","specialMessageHeaderMarginTop":"14px","specialMessageHeaderMarginBottom":"10px","specialMessageItemMarginTop":"0","specialMessageItemMarginBottom":"10px","__typename":"RteThemeSettings"},"tags":{"bgColor":"var(--lia-bs-gray-200)","bgHoverColor":"var(--lia-bs-gray-400)","borderRadius":"var(--lia-bs-border-radius-sm)","color":"var(--lia-bs-body-color)","hoverColor":"var(--lia-bs-body-color)","fontWeight":"var(--lia-font-weight-md)","fontSize":"var(--lia-font-size-xxs)","textTransform":"UPPERCASE","letterSpacing":"0.5px","__typename":"TagsThemeSettings"},"toasts":{"borderRadius":"var(--lia-bs-border-radius)","paddingX":"12px","__typename":"ToastsThemeSettings"},"typography":{"fontFamilyBase":"Atkinson Hyperlegible","fontStyleBase":"NORMAL","fontWeightBase":"400","fontWeightLight":"300","fontWeightNormal":"400","fontWeightMd":"500","fontWeightBold":"700","letterSpacingSm":"normal","letterSpacingXs":"normal","lineHeightBase":"1.3","fontSizeBase":"15px","fontSizeXxs":"11px","fontSizeXs":"12px","fontSizeSm":"13px","fontSizeLg":"20px","fontSizeXl":"24px","smallFontSize":"14px","customFonts":[],"__typename":"TypographyThemeSettings"},"unstyledListItem":{"marginBottomSm":"5px","marginBottomMd":"10px","marginBottomLg":"15px","marginBottomXl":"20px","marginBottomXxl":"25px","__typename":"UnstyledListItemThemeSettings"},"yiq":{"light":"#ffffff","dark":"#000000","__typename":"YiqThemeSettings"},"colorLightness":{"primaryDark":0.36,"primaryLight":0.74,"primaryLighter":0.89,"primaryLightest":0.95,"infoDark":0.39,"infoLight":0.72,"infoLighter":0.85,"infoLightest":0.93,"successDark":0.24,"successLight":0.62,"successLighter":0.8,"successLightest":0.91,"warningDark":0.39,"warningLight":0.68,"warningLighter":0.84,"warningLightest":0.93,"dangerDark":0.41,"dangerLight":0.72,"dangerLighter":0.89,"dangerLightest":0.95,"__typename":"ColorLightnessThemeSettings"},"localOverride":false,"__typename":"Theme"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-1744046271000","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:text:en_US-components/common/EmailVerification-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/common/EmailVerification-1744046271000","value":{"email.verification.title":"Email Verification Required","email.verification.message.update.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. To change your email, visit My Settings.","email.verification.message.resend.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. Resend email."},"localOverride":false},"CachedAsset:text:en_US-pages/tags/TagPage-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-pages/tags/TagPage-1744046271000","value":{"tagPageTitle":"Tag:\"{tagName}\" | {communityTitle}","tagPageForNodeTitle":"Tag:\"{tagName}\" in \"{title}\" | {communityTitle}","name":"Tags Page","tag":"Tag: {tagName}"},"localOverride":false},"CachedAsset:quilt:f5.prod:pages/tags/TagPage:community:zihoc95639-1746691841779":{"__typename":"CachedAsset","id":"quilt:f5.prod:pages/tags/TagPage:community:zihoc95639-1746691841779","value":{"id":"TagPage","container":{"id":"Common","headerProps":{"removeComponents":["community.widget.bannerWidget"],"__typename":"QuiltContainerSectionProps"},"items":[{"id":"tag-header-widget","layout":"ONE_COLUMN","bgColor":"var(--lia-bs-white)","showBorder":"BOTTOM","sectionEditLevel":"LOCKED","columnMap":{"main":[{"id":"tags.widget.TagsHeaderWidget","__typename":"QuiltComponent"}],"__typename":"OneSectionColumns"},"__typename":"OneColumnQuiltSection"},{"id":"messages-list-for-tag-widget","layout":"ONE_COLUMN","columnMap":{"main":[{"id":"messages.widget.messageListForNodeByRecentActivityWidget","props":{"viewVariant":{"type":"inline","props":{"useUnreadCount":true,"useViewCount":true,"useAuthorLogin":true,"clampBodyLines":3,"useAvatar":true,"useBoardIcon":false,"useKudosCount":true,"usePreviewMedia":true,"useTags":false,"useNode":true,"useNodeLink":true,"useTextBody":true,"truncateBodyLength":-1,"useBody":true,"useRepliesCount":true,"useSolvedBadge":true,"timeStampType":"conversation.lastPostingActivityTime","useMessageTimeLink":true,"clampSubjectLines":2}},"panelType":"divider","useTitle":false,"hideIfEmpty":false,"pagerVariant":{"type":"loadMore"},"style":"list","showTabs":true,"tabItemMap":{"default":{"mostRecent":true,"mostRecentUserContent":false,"newest":false},"additional":{"mostKudoed":true,"mostViewed":true,"mostReplies":false,"noReplies":false,"noSolutions":false,"solutions":false}}},"__typename":"QuiltComponent"}],"__typename":"OneSectionColumns"},"__typename":"OneColumnQuiltSection"}],"__typename":"QuiltContainer"},"__typename":"Quilt"},"localOverride":false},"CachedAsset:text:en_US-components/common/ActionFeedback-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/common/ActionFeedback-1744046271000","value":{"joinedGroupHub.title":"Welcome","joinedGroupHub.message":"You are now a member of this group and are subscribed to updates.","groupHubInviteNotFound.title":"Invitation Not Found","groupHubInviteNotFound.message":"Sorry, we could not find your invitation to the group. The owner may have canceled the invite.","groupHubNotFound.title":"Group Not Found","groupHubNotFound.message":"The grouphub you tried to join does not exist. It may have been deleted.","existingGroupHubMember.title":"Already Joined","existingGroupHubMember.message":"You are already a member of this group.","accountLocked.title":"Account Locked","accountLocked.message":"Your account has been locked due to multiple failed attempts. Try again in {lockoutTime} minutes.","editedGroupHub.title":"Changes Saved","editedGroupHub.message":"Your group has been updated.","leftGroupHub.title":"Goodbye","leftGroupHub.message":"You are no longer a member of this group and will not receive future updates.","deletedGroupHub.title":"Deleted","deletedGroupHub.message":"The group has been deleted.","groupHubCreated.title":"Group Created","groupHubCreated.message":"{groupHubName} is ready to use","accountClosed.title":"Account Closed","accountClosed.message":"The account has been closed and you will now be redirected to the homepage","resetTokenExpired.title":"Reset Password Link has Expired","resetTokenExpired.message":"Try resetting your password again","invalidUrl.title":"Invalid URL","invalidUrl.message":"The URL you're using is not recognized. Verify your URL and try again.","accountClosedForUser.title":"Account Closed","accountClosedForUser.message":"{userName}'s account is closed","inviteTokenInvalid.title":"Invitation Invalid","inviteTokenInvalid.message":"Your invitation to the community has been canceled or expired.","inviteTokenError.title":"Invitation Verification Failed","inviteTokenError.message":"The url you are utilizing is not recognized. Verify your URL and try again","pageNotFound.title":"Access Denied","pageNotFound.message":"You do not have access to this area of the community or it doesn't exist","eventAttending.title":"Responded as Attending","eventAttending.message":"You'll be notified when there's new activity and reminded as the event approaches","eventInterested.title":"Responded as Interested","eventInterested.message":"You'll be notified when there's new activity and reminded as the event approaches","eventNotFound.title":"Event Not Found","eventNotFound.message":"The event you tried to respond to does not exist.","redirectToRelatedPage.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.message":"The content you are trying to access is archived","redirectToRelatedPage.message":"The content you are trying to access is archived","relatedUrl.archivalLink.flyoutMessage":"The content you are trying to access is archived View Archived Content"},"localOverride":false},"CachedAsset:quiltWrapper:f5.prod:Common:1746691797456":{"__typename":"CachedAsset","id":"quiltWrapper:f5.prod:Common:1746691797456","value":{"id":"Common","header":{"backgroundImageProps":{"assetName":"header.jpg","backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"LEFT_CENTER","lastModified":"1702932449000","__typename":"BackgroundImageProps"},"backgroundColor":"transparent","items":[{"id":"custom.widget.GainsightShared","props":{"widgetVisibility":"signedInOnly","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.Beta_MetaNav","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"community.widget.navbarWidget","props":{"showUserName":false,"showRegisterLink":true,"style":{"boxShadow":"var(--lia-bs-box-shadow-sm)","linkFontWeight":"700","controllerHighlightColor":"hsla(30, 100%, 50%)","dropdownDividerMarginBottom":"10px","hamburgerBorderHover":"none","linkFontSize":"15px","linkBoxShadowHover":"none","backgroundOpacity":0.4,"controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerBgColor":"transparent","linkTextBorderBottom":"none","hamburgerColor":"var(--lia-nav-controller-icon-color)","brandLogoHeight":"48px","linkLetterSpacing":"normal","linkBgHoverColor":"transparent","collapseMenuDividerOpacity":0.16,"paddingBottom":"10px","dropdownPaddingBottom":"15px","dropdownMenuOffset":"2px","hamburgerBgHoverColor":"transparent","borderBottom":"0","hamburgerBorder":"none","dropdownPaddingX":"10px","brandMarginRightSm":"10px","linkBoxShadow":"none","linkJustifyContent":"center","linkColor":"var(--lia-bs-primary)","collapseMenuDividerBg":"var(--lia-nav-link-color)","dropdownPaddingTop":"10px","controllerHighlightTextColor":"var(--lia-yiq-dark)","background":{"imageAssetName":"","color":"var(--lia-bs-white)","size":"COVER","repeat":"NO_REPEAT","position":"CENTER_CENTER","imageLastModified":""},"linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkHoverColor":"var(--lia-bs-primary)","position":"FIXED","linkBorder":"none","linkTextBorderBottomHover":"2px solid #0C5C8D","brandMarginRight":"30px","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","linkBorderHover":"none","collapseMenuMarginLeft":"20px","linkFontStyle":"NORMAL","linkPaddingX":"10px","paddingTop":"10px","linkPaddingY":"5px","linkTextTransform":"NONE","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkBgColor":"transparent","linkDropdownPaddingY":"9px","controllerIconColor":"#0C5C8D","dropdownDividerMarginTop":"10px","linkGap":"10px","controllerIconHoverColor":"#0C5C8D"},"links":{"sideLinks":[],"mainLinks":[{"children":[{"linkType":"INTERNAL","id":"migrated-link-1","params":{"boardId":"TechnicalForum","categoryId":"Forums"},"routeName":"ForumBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-2","params":{"boardId":"WaterCooler","categoryId":"Forums"},"routeName":"ForumBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-0","params":{"categoryId":"Forums"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-4","params":{"boardId":"codeshare","categoryId":"CrowdSRC"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-5","params":{"boardId":"communityarticles","categoryId":"CrowdSRC"},"routeName":"TkbBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-3","params":{"categoryId":"CrowdSRC"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-7","params":{"boardId":"TechnicalArticles","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"article-series","params":{"boardId":"article-series","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"security-insights","params":{"boardId":"security-insights","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-8","params":{"boardId":"DevCentralNews","categoryId":"Articles"},"routeName":"TkbBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-6","params":{"categoryId":"Articles"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-10","params":{"categoryId":"CommunityGroups"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"migrated-link-11","params":{"categoryId":"F5-Groups"},"routeName":"CategoryPage"}],"linkType":"INTERNAL","id":"migrated-link-9","params":{"categoryId":"GroupsCategory"},"routeName":"CategoryPage"},{"children":[],"linkType":"INTERNAL","id":"migrated-link-12","params":{"boardId":"Events","categoryId":"top"},"routeName":"EventBoardPage"},{"children":[],"linkType":"INTERNAL","id":"migrated-link-13","params":{"boardId":"Suggestions","categoryId":"top"},"routeName":"IdeaBoardPage"},{"children":[],"linkType":"EXTERNAL","id":"Common-external-link","url":"https://community.f5.com/c/how-do-i","target":"SELF"}]},"className":"QuiltComponent_lia-component-edit-mode__lQ9Z6","showSearchIcon":false},"__typename":"QuiltComponent"},{"id":"community.widget.bannerWidget","props":{"backgroundColor":"transparent","visualEffects":{"showBottomBorder":false},"backgroundImageProps":{"backgroundSize":"COVER","backgroundPosition":"CENTER_CENTER","backgroundRepeat":"NO_REPEAT"},"fontColor":"#222222"},"__typename":"QuiltComponent"},{"id":"community.widget.breadcrumbWidget","props":{"backgroundColor":"var(--lia-bs-primary)","linkHighlightColor":"#FFFFFF","visualEffects":{"showBottomBorder":false},"backgroundOpacity":60,"linkTextColor":"#FFFFFF"},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"footer":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"var(--lia-bs-body-color)","items":[{"id":"custom.widget.Beta_Footer","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.Tag_Manager_Helper","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.Consent_Blackbar","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"__typename":"QuiltWrapper","localOverride":false},"localOverride":false},"CachedAsset:component:custom.widget.GainsightShared-en-us-1746691863249":{"__typename":"CachedAsset","id":"component:custom.widget.GainsightShared-en-us-1746691863249","value":{"component":{"id":"custom.widget.GainsightShared","template":{"id":"GainsightShared","markupLanguage":"HTML","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"Shared functions for Gainsight integration","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.GainsightShared","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"TEXTHTML","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"Shared functions for Gainsight integration","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Beta_MetaNav-en-us-1746691863249":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_MetaNav-en-us-1746691863249","value":{"component":{"id":"custom.widget.Beta_MetaNav","template":{"id":"Beta_MetaNav","markupLanguage":"HANDLEBARS","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"MetaNav menu at the top of every page.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Beta_MetaNav","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"MetaNav menu at the top of every page.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Beta_Footer-en-us-1746691863249":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_Footer-en-us-1746691863249","value":{"component":{"id":"custom.widget.Beta_Footer","template":{"id":"Beta_Footer","markupLanguage":"HANDLEBARS","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"DevCentral´s custom footer.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Beta_Footer","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"DevCentral´s custom footer.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Tag_Manager_Helper-en-us-1746691863249":{"__typename":"CachedAsset","id":"component:custom.widget.Tag_Manager_Helper-en-us-1746691863249","value":{"component":{"id":"custom.widget.Tag_Manager_Helper","template":{"id":"Tag_Manager_Helper","markupLanguage":"HANDLEBARS","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"Helper widget to inject Tag Manager scripts into head element","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Tag_Manager_Helper","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"Helper widget to inject Tag Manager scripts into head element","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Consent_Blackbar-en-us-1746691863249":{"__typename":"CachedAsset","id":"component:custom.widget.Consent_Blackbar-en-us-1746691863249","value":{"component":{"id":"custom.widget.Consent_Blackbar","template":{"id":"Consent_Blackbar","markupLanguage":"HTML","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Consent_Blackbar","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"TEXTHTML","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:text:en_US-components/community/Breadcrumb-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Breadcrumb-1744046271000","value":{"navLabel":"Breadcrumbs","dropdown":"Additional parent page navigation"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagsHeaderWidget-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagsHeaderWidget-1744046271000","value":{"tag":"{tagName}","topicsCount":"{count} {count, plural, one {Topic} other {Topics}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageListForNodeByRecentActivityWidget-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageListForNodeByRecentActivityWidget-1744046271000","value":{"title@userScope:other":"Recent Content","title@userScope:self":"Contributions","title@board:FORUM@userScope:other":"Recent Discussions","title@board:BLOG@userScope:other":"Recent Blogs","emptyDescription":"No content to show","MessageListForNodeByRecentActivityWidgetEditor.nodeScope.label":"Scope","title@instance:1706288370055":"Content Feed","title@instance:1743095186784":"Most Recent Updates","title@instance:1704317906837":"Content Feed","title@instance:1743095018194":"Most Recent Updates","title@instance:1702668293472":"Community Feed","title@instance:1743095117047":"Most Recent Updates","title@instance:1704319314827":"Blog Feed","title@instance:1743095235555":"Most Recent Updates","title@instance:1704320290851":"My Contributions","title@instance:1703720491809":"Forum Feed","title@instance:1743095311723":"Most Recent Updates","title@instance:1703028709746":"Group Content Feed","title@instance:VTsglH":"Content Feed"},"localOverride":false},"Category:category:Forums":{"__typename":"Category","id":"category:Forums","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"displayId":"Forums"},"Forum:board:TechnicalForum":{"__typename":"Forum","id":"board:TechnicalForum","forumPolicies":{"__typename":"ForumPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"displayId":"TechnicalForum","nodeType":"board","conversationStyle":"FORUM","title":"Technical Forum","shortTitle":"Technical Forum","parent":{"__ref":"Category:category:Forums"}},"Forum:board:WaterCooler":{"__typename":"Forum","id":"board:WaterCooler","forumPolicies":{"__typename":"ForumPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"displayId":"WaterCooler","nodeType":"board","conversationStyle":"FORUM","title":"Water Cooler","shortTitle":"Water Cooler","parent":{"__ref":"Category:category:Forums"}},"Category:category:Articles":{"__typename":"Category","id":"category:Articles","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"displayId":"Articles"},"Tkb:board:TechnicalArticles":{"__typename":"Tkb","id":"board:TechnicalArticles","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"displayId":"TechnicalArticles","nodeType":"board","conversationStyle":"TKB","title":"Technical Articles","shortTitle":"Technical Articles","parent":{"__ref":"Category:category:Articles"}},"Tkb:board:DevCentralNews":{"__typename":"Tkb","id":"board:DevCentralNews","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:GroupsCategory":{"__typename":"Category","id":"category:GroupsCategory","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:F5-Groups":{"__typename":"Category","id":"category:F5-Groups","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:CommunityGroups":{"__typename":"Category","id":"category:CommunityGroups","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Occasion:board:Events":{"__typename":"Occasion","id":"board:Events","boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"occasionPolicies":{"__typename":"OccasionPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Idea:board:Suggestions":{"__typename":"Idea","id":"board:Suggestions","boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"ideaPolicies":{"__typename":"IdeaPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:CrowdSRC":{"__typename":"Category","id":"category:CrowdSRC","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"displayId":"CrowdSRC"},"Tkb:board:codeshare":{"__typename":"Tkb","id":"board:codeshare","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"displayId":"codeshare","nodeType":"board","conversationStyle":"TKB","title":"CodeShare","shortTitle":"CodeShare","parent":{"__ref":"Category:category:CrowdSRC"}},"Tkb:board:communityarticles":{"__typename":"Tkb","id":"board:communityarticles","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:security-insights":{"__typename":"Tkb","id":"board:security-insights","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:article-series":{"__typename":"Tkb","id":"board:article-series","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Conversation:conversation:341070":{"__typename":"Conversation","id":"conversation:341070","topic":{"__typename":"TkbTopicMessage","uid":341070},"lastPostingActivityTime":"2025-04-30T17:03:11.284-07:00","solved":false},"User:user:425632":{"__typename":"User","uid":425632,"login":"ashrafelsayelshabany","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS00MjU2MzItMjYyMDNpODBDRDBENUUxOUIyNzVGMA"},"id":"user:425632"},"TkbTopicMessage:message:341070":{"__typename":"TkbTopicMessage","subject":"Automating F5 Licensing - without direct internet access","conversation":{"__ref":"Conversation:conversation:341070"},"id":"message:341070","revisionNum":2,"uid":341070,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:425632"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":73},"postTime":"2025-04-30T10:04:33.425-07:00","lastPublishTime":"2025-04-30T11:28:07.763-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Hello DevCentral Community! I'm excited to share a project I've been working on recently: **Automating F5 BIG-IP VE Licensing** without needing direct internet access! The project covers: Retrieving a Dossier automatically via iControl REST API. Interacting with F5 licensing servers through proxies or offline. Re-activating licenses post-upgrade using custom scripts. Full Python 3 support (moving away from BigSuds/Python 2 limitations). ✅ The idea is to help users who need to automate the licensing process, especially for secure or offline environments. I'll be sharing: Scripts Use cases Lessons learned Tips for real-world deployments If you're interested in automating your BIG-IP licensing process, feel free to follow along! Feedback, ideas, or collaboration is most welcome! 🚀 import requests\nimport json\nimport urllib3\n\nurllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)\n\nclass BigIPLicenseManager:\n def __init__(self, host, username, password, registration_key):\n self.host = host\n self.username = username\n self.password = password\n self.registration_key = registration_key\n self.base_url = f\"https://{self.host}/mgmt/tm/sys/license\"\n self.headers = {'Content-Type': 'application/json'}\n\n def get_dossier(self):\n payload = {\n \"command\": \"install\",\n \"registrationKey\": self.registration_key\n }\n response = requests.post(\n self.base_url,\n auth=(self.username, self.password),\n headers=self.headers,\n json=payload,\n verify=False\n )\n if response.status_code == 200:\n data = response.json()\n dossier = data.get('dossier')\n if dossier:\n print(\"[+] Dossier retrieved successfully.\")\n return dossier\n else:\n print(\"[-] No dossier found in response.\")\n return None\n else:\n print(f\"[-] Failed to retrieve dossier: {response.text}\")\n return None\n\n def install_license(self, license_text):\n payload = {\n \"command\": \"install\",\n \"licenseText\": license_text\n }\n response = requests.post(\n self.base_url,\n auth=(self.username, self.password),\n headers=self.headers,\n json=payload,\n verify=False\n )\n if response.status_code == 200:\n print(\"[+] License installed successfully.\")\n else:\n print(f\"[-] Failed to install license: {response.text}\")\n\nif __name__ == \"__main__\":\n # Define your BIG-IP credentials and registration key here\n bigip_host = \"192.168.1.245\"\n bigip_username = \"admin\"\n bigip_password = \"admin\"\n registration_key = \"AAAAA-BBBBB-CCCCC-DDDDD-EEEEE\"\n\n manager = BigIPLicenseManager(\n bigip_host,\n bigip_username,\n bigip_password,\n registration_key\n )\n\n dossier = manager.get_dossier()\n if dossier:\n # Print the dossier to manually activate it via activate.f5.com\n print(\"\\n[!] Submit the following dossier to F5 activation server:\")\n print(dossier)\n\n # After getting the license text (offline or from a licensing server)\n license_text = input(\"\\nPaste the license text here:\\n\")\n\n manager.install_license(license_text.strip()) ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"3413","kudosSumWeight":1,"repliesCount":1,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:341018":{"__typename":"Conversation","id":"conversation:341018","topic":{"__typename":"ForumTopicMessage","uid":341018},"lastPostingActivityTime":"2025-04-30T10:10:18.462-07:00","solved":false},"ForumTopicMessage:message:341018":{"__typename":"ForumTopicMessage","subject":"[Sharing My Journey: Automating F5 Licensing]","conversation":{"__ref":"Conversation:conversation:341018"},"id":"message:341018","revisionNum":2,"uid":341018,"depth":0,"board":{"__ref":"Forum:board:WaterCooler"},"author":{"__ref":"User:user:425632"},"metrics":{"__typename":"MessageMetrics","views":43},"postTime":"2025-04-27T08:29:14.409-07:00","lastPublishTime":"2025-04-30T10:10:18.462-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" editors note: Moved to Codeshare - Automating F5 Licensing - without direct internet access | DevCentral ---Hello DevCentral Community! \n I'm excited to share a project I've been working on recently: **Automating F5 BIG-IP VE Licensing** without needing direct internet access! \n The project covers: - Retrieving a Dossier automatically via iControl REST API. - Interacting with F5 licensing servers through proxies or offline. - Re-activating licenses post-upgrade using custom scripts. - Full Python 3 support (moving away from BigSuds/Python 2 limitations). \n ✅ The idea is to help users who need to automate the licensing process, especially for secure or offline environments. \n I'll be sharing: - Scripts - Use cases - Lessons learned - Tips for real-world deployments \n If you're interested in automating your BIG-IP licensing process, feel free to follow along! Feedback, ideas, or collaboration is most welcome! 🚀 \n #F5 #BIGIP #Automation #DevCentral #Python3 #Licensing \n --- \n 🔗 Upcoming posts: Detailed code examples, error handling tips, and best practices. \n Thanks to the amazing DevCentral community for inspiring me to contribute and share! \n ........................................................................................................................................................................................................................................... \n import requests import json import urllib3 \n urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) \n class BigIPLicenseManager: def __init__(self, host, username, password, registration_key): self.host = host self.username = username self.password = password self.registration_key = registration_key self.base_url = f\"https://{self.host}/mgmt/tm/sys/license\" self.headers = {'Content-Type': 'application/json'} \n def get_dossier(self): payload = { \"command\": \"install\", \"registrationKey\": self.registration_key } response = requests.post( self.base_url, auth=(self.username, self.password), headers=self.headers, json=payload, verify=False ) if response.status_code == 200: data = response.json() dossier = data.get('dossier') if dossier: print(\"[+] Dossier retrieved successfully.\") return dossier else: print(\"[-] No dossier found in response.\") return None else: print(f\"[-] Failed to retrieve dossier: {response.text}\") return None \n def install_license(self, license_text): payload = { \"command\": \"install\", \"licenseText\": license_text } response = requests.post( self.base_url, auth=(self.username, self.password), headers=self.headers, json=payload, verify=False ) if response.status_code == 200: print(\"[+] License installed successfully.\") else: print(f\"[-] Failed to install license: {response.text}\") \n if __name__ == \"__main__\": # Define your BIG-IP credentials and registration key here bigip_host = \"192.168.1.245\" bigip_username = \"admin\" bigip_password = \"admin\" registration_key = \"AAAAA-BBBBB-CCCCC-DDDDD-EEEEE\" \n manager = BigIPLicenseManager( bigip_host, bigip_username, bigip_password, registration_key ) \n dossier = manager.get_dossier() if dossier: # Print the dossier to manually activate it via activate.f5.com print(\"\\n[!] Submit the following dossier to F5 activation server:\") print(dossier) \n # After getting the license text (offline or from a licensing server) license_text = input(\"\\nPaste the license text here:\\n\") \n manager.install_license(license_text.strip()) ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"5592","kudosSumWeight":0,"repliesCount":3,"readOnly":true,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:288887":{"__typename":"Conversation","id":"conversation:288887","topic":{"__typename":"TkbTopicMessage","uid":288887},"lastPostingActivityTime":"2025-01-09T05:35:13.957-08:00","solved":false},"User:user:172159":{"__typename":"User","uid":172159,"login":"Leon_Seng","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0xNzIxNTktMjA5NDNpQTcyQThGQzE5NUQ0MzZFMg"},"id":"user:172159"},"TkbTopicMessage:message:288887":{"__typename":"TkbTopicMessage","subject":"TACACS+ External Monitor (Python)","conversation":{"__ref":"Conversation:conversation:288887"},"id":"message:288887","revisionNum":2,"uid":288887,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:172159"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":1310},"postTime":"2021-09-15T16:22:58.000-07:00","lastPublishTime":"2025-01-09T05:35:13.957-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: \n This script is an external monitor for TACACS+ that simulates a TACACS+ client authenticating a test user, and marks the status of a pool member as up if the authentication is successful. If the connection is down/times out, or the authentication fails due to invalid account settings, the script marks the pool member status as down. \n \n This is heavily inspired by the Radius External Monitor (Python) by AlanTen. \n How to use this snippet: \n Prerequisite \n \n This script uses the TACACS+ Python client by Ansible (tested on version 2.6). \n \n \n Create the directory /config/eav/tacacs_plus on BIG-IP \n Copy all contents from tacacs_plus package into /config/eav/tacacs_plus. \n \n \n You may also need to download six.py from https://raw.githubusercontent.com/benjaminp/six/master/six.py and place it in /config/eav/tacacs_plus. \n You will need to have a test account provisioned on the TACACS+ server for the script to perform authentication. \n \n \n Installation \n On BIG-IP, import the code snippet below as an External Monitor Program File. \n \n Monitor Configuration \n Set up an External monitor with the imported file, and configure it with the following environment variables: \n \n KEY: TACACS+ server secret \n USER: Username for test account \n PASSWORD: Password for test account \n MOD_PATH: Path to location of Python package tacacs_plus, default: /config/eav \n TIMEOUT: Duration to wait for connectivity to TACACS server to be established, default: 3 \n \n Troubleshooting \n SSH to BIG-IP and run the script locally \n $ cd /config/filestore/files_d/Common_d/external_monitor_d/\n\n# Get name of uploaded file, e.g.:\n$ ls -la\n...\n-rwxr-xr-x. 1 tomcat tomcat 1883 2021-09-17 04:05 :Common:tacacs-monitor_39568_7\n\n# Run the script with the corresponding variables\n$ KEY=<my_tacacs_key> USER=<testuser> PASSWORD=<supersecure> python <external program file, e.g.:Common:tacacs-monitor_39568_7> <TACACS+ server IP> <TACACS+ server port>\n \n \n Code : \n #!/usr/bin/env python\n#\n# Filename : tacacs_plus_mon.py\n# Author : Leon Seng\n# Version : 1.2\n# Date : 2021/09/21\n# Python ver: 2.6+\n# F5 version: 12.1+\n# \n# ========== Installation\n# Import this script via GUI:\n# System > File Management > External Monitor Program File List > Import...\n# Name it however you want.\n# Get, modify and copy the following modules:\n\n# ========== Required modules\n# -- six --\n# https://pypi.org/project/six/\n# Copy six.py into /config/eav\n#\n# -- tacacs_plus --\n# https://pypi.org/project/tacacs_plus/ | https://github.com/ansible/tacacs_plus\n# Copy tacacs_plus directory into /config/eav\n\n# ========== Environment Variables\n# NODE_IP - Supplied by F5 monitor as first argument\n# NODE_PORT - Supplied by F5 monitor as second argument\n# KEY - TACACS+ server secret\n# USER - Username for test account\n# PASSWORD - Password for test account\n# MOD_PATH - Path to location of Python package tacacs_plus, default: /config/eav\n# TIMEOUT - Duration to wait for connectivity to TACACS server to be established, default: 3\n\nimport os\nimport socket\nimport sys\n\nif os.environ.get('MOD_PATH'):\n sys.path.append(os.environ.get('MOD_PATH'))\nelse:\n sys.path.append('/config/eav')\n\n# https://github.com/ansible/tacacs_plus\nfrom tacacs_plus.client import TACACSClient\n\nnode_ip = sys.argv[1]\nnode_port = int(sys.argv[2])\nkey = os.environ.get(\"KEY\")\nuser = os.environ.get(\"USER\")\npassword = os.environ.get(\"PASSWORD\")\ntimeout = int(os.environ.get(\"TIMEOUT\", 3))\n\n# Determine if node IP is IPv4 or IPv6\nfamily = None\ntry:\n socket.inet_pton(socket.AF_INET, node_ip)\n family = socket.AF_INET\nexcept socket.error: # not a valid address\n try:\n socket.inet_pton(socket.AF_INET6, node_ip)\n family = socket.AF_INET6\n except socket.error:\n sys.exit(1)\n\n# Authenticate against TACACS server\nclient = TACACSClient(node_ip, node_port, key, timeout=timeout, family=family)\ntry:\n auth = client.authenticate(user, password)\n if auth.valid:\n print \"up\"\nexcept socket.error:\n # EAV script marks node as DOWN when no output is present\n pass \n Tested this on version: \n 12.1 ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"4351","kudosSumWeight":1,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:284930":{"__typename":"Conversation","id":"conversation:284930","topic":{"__typename":"TkbTopicMessage","uid":284930},"lastPostingActivityTime":"2024-12-17T19:36:21.859-08:00","solved":false},"User:user:51154":{"__typename":"User","uid":51154,"login":"JRahm","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS01MTE1NC1uYzdSVFk?image-coordinates=0%2C0%2C1067%2C1067"},"id":"user:51154"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQ5MzAtMTAxMDFpOEY4QTY2NDAyMjlEODAxOA?revision=1\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQ5MzAtMTAxMDFpOEY4QTY2NDAyMjlEODAxOA?revision=1","title":"0EM1T000003Jj5t.png","associationType":"BODY","width":781,"height":205,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQ5MzAtNzAzMmlENkY2RTlDQjM5QzMyODYw?revision=1\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQ5MzAtNzAzMmlENkY2RTlDQjM5QzMyODYw?revision=1","title":"0EM1T000003Jj63.png","associationType":"BODY","width":348,"height":110,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQ5MzAtODg1NGlFOTlCNUFEN0ZCNjlFN0Ex?revision=1\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQ5MzAtODg1NGlFOTlCNUFEN0ZCNjlFN0Ex?revision=1","title":"0EM1T000003Jj6D.png","associationType":"BODY","width":533,"height":137,"altText":null},"TkbTopicMessage:message:284930":{"__typename":"TkbTopicMessage","subject":"Managing ZoneRunner Resource Records with Bigsuds","conversation":{"__ref":"Conversation:conversation:284930"},"id":"message:284930","revisionNum":1,"uid":284930,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:51154"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":1101},"postTime":"2021-09-23T10:54:35.000-07:00","lastPublishTime":"2021-09-23T10:54:35.000-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Over the last several years, there have been questions internal and external on how to manage ZoneRunner (the GUI tool in F5 DNS that allows you to manage DNS zones and records) resources via the REST interface. But that's a no can do with the iControl REST--it doesn't have that functionality. It was brought to my attention by one of our solutions engineers that a customer is using some methods in the SOAP interface that allows you to do just that...which was news to me! The things you learn... In this article, I'll highlight a few of the methods available to you and work on a sample domain in the python module bigsuds that utilizes the suds SOAP library for communication duties with the BIG-IP iControl SOAP interface. \n\n Test Domain & Procedure \n\n For demonstration purposes, I'll create a domain in the external view, dctest1.local, with the following attributes that mirrors nearly identically one I created in the GUI: \n\n Type: master Zone Name: dctest1.local. Zone File Name: db.external.dctest1.local. Options: allow-update from localhost TTL: 500 SOA: ns1.dctest1.local. Email: hostmaster.ns1.dctest1.local. Serial: 2021092201 Refresh: 10800 Retry: 3600 Expire: 604800 Negative TTL: 60 \n\n I'll also add a couple type A records to that domain: \n\n name: mail.dctest1.local., address: 10.0.2.25, TTL: 86400 name: www.dctest1.local., address: 10.0.2.80, TTL: 3600 \n\n After adding the records, I'll update one of them, changing the IP and the TTL: \n\n name: mail.dctest1.local., address: 10.0.2.110, ttl: 900 \n\n Then I'll delete the other one: \n\n name: www.dctest1.local., address: 10.0.2.80, TTL: 3600 \n\n And finally, I'll delete the zone: \n\n name: dctest1.local. \n\n ZoneRunner Methods \n\n All the methods can be found on Clouddocs in the ZoneRunner, Zone, and ResourceRecord method pages. The specific methods we'll use in our highlight real are: \n\n Management.ResourceRecord.add_a Management.ResourceRecord.delete_a Management.ResourceRecord.get_rrs Management.ResourceRecord.update_a Management.Zone.add_zone_text Management.Zone.get_zone_v2 Management.Zone.zone_exist \n\n With each method, there is a data structure that the interface expects. Each link above provides the details, but let's look at an example with the add_a method. The method requires three parameters, view_zones, a_records, and sync_ptrs, which the image of the table shows below. \n\n The boolean is just a True/False value in a list. The reason the list ( [] ) is there for all the attributes is because you can send a single request to update more than one zone, and add more than one record within each zone if desired. The data structure for view_zones and a_records is in the following two images. \n\n Now that we have an idea of what the methods require, let's take a look at some code! \n\n Methods In Action \n\n First, I import bigsuds and initialize the BIG-IP. The arguments are ordered in bigsuds for host, username, and password. If the default “admin/admin” is used, they are assumed, as is shown here. \n\n \nimport bigsuds\n\nb = bigsuds.BIGIP(hostname='ltm3.test.local')\n \n\n Next, I need to format the ViewZone data in a native python dictionary, and then I check for the existence of that zone. \n\n \nzone_view = {'view_name': 'external',\n 'zone_name': 'dctest1.local.'\n }\nb.Management.Zone.zone_exist([zone_view])\n\n# [0]\n \n\n Note that the return value, which should be a list of booleans, is a list with a 0. I’m guessing that’s either suds or the bigsuds implementation doing that, but it’s important to note if you’re checking for a boolean False. It’s also necessary to set the booleans as 0 or 1 as well when sending requests to BIG-IP with bigsuds. \n\n Now I will create the zone since it does not yet exist. From the add_zone_text method description on Clouddocs, note that I need to supply, in separate parameters, the zone info, the appropriate zone records, and the boolean to sync reverse records or not. \n\n \nzone_add_info = {'view_name': 'external',\n 'zone_name': 'dctest1.local.',\n 'zone_type': 'MASTER',\n 'zone_file': 'db.external.dctest1.local.',\n 'option_seq': ['allow-update { localhost;};']}\nzone_add_records = 'dctest1.local. 500 IN SOA ns1.dctest1.local. hostmaster.ns1.dctest1.local. 2021092201 10800 3600 604800 60;\\n' \\\n 'dctest1.local. 3600 IN NS ns1.dctest1.local.;\\n' \\\n 'ns1.dctest1.local. 3600 IN A 10.0.2.1;'\n\nb.Management.Zone.add_zone_text([zone_add_info],\n [[zone_add_records]],\n [0])\nb.Management.Zone.zone_exist([zone_view])\n\n# [1]\n \n\n Note that the strings here require a detailed understanding of DNS record formatting, the individual fields are not parameters that can be set like in the ZoneRunner GUI. But, I am confident there is an abundance of modules that manage DNS formatting in the python ecosystem that could simplify the data structuring. After creating the zone, another check to see if the zone exists results in a true condition. Huzzah! \n\n Now I’ll check the zone info and the existing records for that zone. \n\n \nzone = b.Management.Zone.get_zone_v2([zone_view])\nfor k, v in zone[0].items():\n print(f'{k}: {v}')\n\n# view_name: external\n# zone_name: dctest1.local.\n# zone_type: MASTER\n# zone_file: \"db.external.dctest1.local.\"\n# option_seq: ['allow-update { localhost;};']\n\nrrs = b.Management.ResourceRecord.get_rrs([zone_view])\nfor rr in rrs[0]:\n print(rr)\n\n# dctest1.local. 500 IN SOA ns1.dctest1.local. hostmaster.ns1.dctest1.local. 2021092201 10800 3600 604800 60\n# dctest1.local. 3600 IN NS ns1.dctest1.local.\n# ns1.dctest1.local. 3600 IN A 10.0.2.1\n \n\n Everything checks outs! Next I’ll create the A records for the mail and www services. I’m going to add a filter to only check for the mail/www services for printing to cut down on the lines, but know that they’re still there going forward. \n\n \na1 = {'domain_name': 'mail.dctest1.local.',\n 'ip_address': '10.0.2.25',\n 'ttl': 86400}\na2 = {'domain_name': 'www.dctest1.local.',\n 'ip_address': '10.0.2.80',\n 'ttl': 3600}\nb.Management.ResourceRecord.add_a(view_zones=[zone_view],\n a_records=[[a1, a2]],\n sync_ptrs=[0])\nrrs = b.Management.ResourceRecord.get_rrs([zone_view])\nfor rr in rrs[0]:\n if any(item in rr for item in ['mail', 'www']):\n print(rr)\n\n# mail.dctest1.local. 86400 IN A 10.0.2.25\n# www.dctest1.local. 3600 IN A 10.0.2.80\n \n\n Here you can see that I’m adding two records to the zone specified and not creating the reverse records (not included for brevity, but in prod would be likely). Now I’ll update the mail address and TTL. \n\n \nb.Management.ResourceRecord.update_a([zone_view],\n [[a1]],\n [[a1_update]],\n [0])\nrrs = b.Management.ResourceRecord.get_rrs([zone_view])\nfor rr in rrs[0]:\n if any(item in rr for item in ['mail', 'www']):\n print(rr)\n\n# mail.dctest1.local. 900 IN A 10.0.2.110\n# www.dctest1.local. 3600 IN A 10.0.2.80\n \n\n You can see that the address and TTL updated as expected. Note that with the update_/N/ methods, you need to provide the old and new, not just the new. Let’s get destruction and delete the www record! \n\n \nb.Management.ResourceRecord.delete_a([zone_view],\n [[a2]],\n [0])\nrrs = b.Management.ResourceRecord.get_rrs([zone_view])\nfor rr in rrs[0]:\n if any(item in rr for item in ['mail', 'www']):\n print(rr)\n\n# mail.dctest1.local. 900 IN A 10.0.2.110\n \n\n And your web service is now unreachable via DNS. Congratulations! But there’s more damage we can do: it’s time to delete the whole zone. \n\n \nb.Management.Zone.delete_zone([zone_view])\nb.Management.Zone.zone_exist([zone_view])\n\n# [0]\n \n\n And that’s a wrap! As I said, it’s been years since I have spent time with the iControl SOAP interface. It’s nice to know that even though most of what we do is done through REST, imperatively or declaratively, that some missing functionality in that interface is still alive and kicking via SOAP. H/T to Scott Huddy for the nudge to investigate this. Questions? Drop me a comment below. Happy coding! A gist of these samples is available on GitHub. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"8628","kudosSumWeight":2,"repliesCount":2,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQ5MzAtMTAxMDFpOEY4QTY2NDAyMjlEODAxOA?revision=1\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQ5MzAtNzAzMmlENkY2RTlDQjM5QzMyODYw?revision=1\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQ5MzAtODg1NGlFOTlCNUFEN0ZCNjlFN0Ex?revision=1\"}"}}],"totalCount":3,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:333687":{"__typename":"Conversation","id":"conversation:333687","topic":{"__typename":"ForumTopicMessage","uid":333687},"lastPostingActivityTime":"2024-12-01T22:52:43.952-08:00","solved":false},"User:user:26046":{"__typename":"User","uid":26046,"login":"cathy_123","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-10.svg?time=0"},"id":"user:26046"},"ForumTopicMessage:message:333687":{"__typename":"ForumTopicMessage","subject":"Python script to get the SSL profile of a VIP","conversation":{"__ref":"Conversation:conversation:333687"},"id":"message:333687","revisionNum":1,"uid":333687,"depth":0,"board":{"__ref":"Forum:board:TechnicalForum"},"author":{"__ref":"User:user:26046"},"metrics":{"__typename":"MessageMetrics","views":132},"postTime":"2024-08-29T23:28:10.359-07:00","lastPublishTime":"2024-08-29T23:28:10.359-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Hello guys I am creating an SSL automation and I am trying to get the ssl profile from inputted VIP.. I am using F5 rest api and I am not seeing much differences on the contents when I use this url url = f\"https://{f5_hostname}/mgmt/tm/ltm/virtual/~Common~{vip_name}\" and filter using profilesReference it gave me all profiles sample below. From below contents, I dont know how to filter further to get the sslprofile as you see almost all of them has the same content, I cannot differentiate the ssl profile from others. any other way how to get the sslprofile from a VIP using python script? { \"kind\": \"tm:ltm:virtual:profiles:profilesstate\", \"name\": \"myssslprofile.com\", ->>>> this is the ssl profile \"partition\": \"Common\", \"fullPath\": \"/Common/myssslprofile.com\", \"generation\": 1, \"selfLink\": \"https://localhost/mgmt/tm/ltm/virtual/exampleVIP.com/profiles/~Common~myssslprofile.com?ver=16.x.x.x\", \"context\": \"clientside\" }, { \"kind\": \"tm:ltm:virtual:profiles:profilesstate\", \"name\": \"tcp-lan-optimized\", \"partition\": \"Common\", \"fullPath\": \"/Common/tcp-lan-optimized\", \"generation\": 1, \"selfLink\": \"https://localhost/mgmt/tm/ltm/virtual/exampleVIP.com/profiles/~Common~tcp-lan-optimized?ver=16.x.x.x\", \"context\": \"serverside\" }, { \"kind\": \"tm:ltm:virtual:profiles:profilesstate\", \"name\": \"tcp-wan-optimized\", \"partition\": \"Common\", \"fullPath\": \"/Common/tcp-wan-optimized\", \"generation\": 1, \"selfLink\": \"https://localhost/mgmt/tm/ltm/virtual/exampleVIP.com/profiles/~Common~tcp-wan-optimized?ver=16.x.x.x\", \"context\": \"clientside\" }, { \"kind\": \"tm:ltm:virtual:profiles:profilesstate\", \"name\": \"anotheprofile\", \"partition\": \"Common\", \"fullPath\": \"/Common/anotheprofile\", \"generation\": 1, \"selfLink\": \"https://localhost/mgmt/tm/ltm/virtual/exampleVIP.com/profiles/~Common~anotheprofile?ver=16.x.x.x\", \"context\": \"serverside\" }, ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"3326","kudosSumWeight":0,"repliesCount":6,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:290993":{"__typename":"Conversation","id":"conversation:290993","topic":{"__typename":"TkbTopicMessage","uid":290993},"lastPostingActivityTime":"2024-11-21T03:23:59.412-08:00","solved":false},"User:user:195323":{"__typename":"User","uid":195323,"login":"Mark_Lloyd","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-7.svg?time=0"},"id":"user:195323"},"TkbTopicMessage:message:290993":{"__typename":"TkbTopicMessage","subject":"Python module to post and retrieve IControl Rest JSON objects for AVR statistics","conversation":{"__ref":"Conversation:conversation:290993"},"id":"message:290993","revisionNum":2,"uid":290993,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:195323"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":408},"postTime":"2016-06-26T14:05:08.000-07:00","lastPublishTime":"2023-06-05T22:51:27.504-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Problem this snippet solves: This module simplifies making Python dictionary objects that are converted to IControl rest AVR JSON objects. It also handles making AVR requests and retrieving results as well allowing multiple AVR requests to be queued, posted and retrieved. It also has some basis type checking for the elements of a AVR request. This module requires Bigip 12.1 on the target that statistics are retrieved. How to use this snippet: The main class is rest_avr.avr_req. It is a dictionary class that maps directly to an IControl Rest AVR JSON request as translated by json.dumps. Each dictionary element is an object derived from a customer class for each part of the request. The element classes have add() and clear() functions. if the element class only allows one entry the add() function will replace the existing entry, otherwise it will append the entry to the request element. The rest_avr.avr_req class also has functions to populate the HTTP host and authentication values for the target system. \n rest_avr.avr_req.post_and_response returns the Python representation of the JSON result of the query. \n rest_avr.avr_req.add_to_queue() adds the currently constructed request to a queue of requests to post. \n rest_avr.avr_req.post_and_response_queue() returns a python list of results of queued queries. \n The following code sample constructs, posts and returns results for an AVR statistics request for specific DNS records and a specificrecord type, then queues multiple quests and posts and returns results. \n #!/usr/bin/python\nimport json\nimport sys\nimport time\nimport rest_avr\n\n#print rest_avr.ShowAVRJsonApi\n\n#Populate the url\n\navr_dns_req=rest_avr.avr_req()\navr_dns_req.auth('admin','admin')\navr_dns_req.url_base('10.10.2.113','dns')\n\n#Populate the json object\n\navr_dns_req['analyticsModule'].add('dns')\navr_dns_req['reportFeatures'].add('time-aggregated')\navr_dns_req['entityFilters'].add('domain-name', 'OPERATOR_TYPE_EQUAL', ['test2.test1.com','test1.test1.com'])\navr_dns_req['entityFilters'].add('query-type', 'OPERATOR_TYPE_EQUAL', ['a'])\navr_dns_req['viewMetrics'].add('packets')\navr_dns_req['viewDimensions'].add('domain-name')\navr_dns_req['metricFilters'].add('packets', 'OPERATOR_TYPE_GREATER_THAN', 0)\navr_dns_req['sortByMetrics'].add('packets', 'ascending')\navr_dns_req['pagination'].add(20, 0)\navr_dns_req['timeRange'].add(1461778251000000, None)\n\n#Post and retrieve results.\n\nresult_py=avr_dns_req.post_and_response()\n\nif result_py != None:\n print ('\\n' + result_py['results']['timeAggregated'][0]['dimensions'][0]['value'] + \" \" + result_py['results']['timeAggregated'][0]['metricValues'][0]['value'] + '\\n')\n\nelse:\n print result_py.error_layer\n print result_py.error_code\n print result_py.error_text\n\n# Now add multiple requests to a queue\navr_dns_req.add_to_queue()\n\navr_dns_req['entityFilters'].clear()\navr_dns_req['entityFilters'].add('query-type', 'OPERATOR_TYPE_EQUAL', ['aaaa'])\navr_dns_req.add_to_queue()\n\n#post and retrieve queued results\nresult_py_q=avr_dns_req.post_and_response_queue()\n\nfor result_py in result_py_q:\n\n if result_py != None:\n print ('\\n' + result_py['results']['timeAggregated'][0]['dimensions'][0]['value'] + \" \" + result_py['results']['timeAggregated'][0]['metricValues'][0]['value'] + '\\n')\n else:\n print result_py.error_layer\n print result_py.error_code\n print result_py.error_text\n Code : \"\"\"\nrest_avr provides a python interface to Bigip AVR statistics using the REST API. The main Python rest_avr.avr_req\nobject is a Python dictionary that maps to a JSON object that can be processed with the json.dumps() function\n\nAn IControl Rest AVR JSON request and response can be initiated with avr_req.post_and_response\n\nThe simple description of the API can is available at avr_req.ShowJsonApi()\n\nEach of these modules has a method to add single or multiple elements as appropriate to the specific module.\nOnce these elements are are populated a RestAPI request can be made with results returned as a python\nrepresentation.\n\n\navr_req.auth(user, passw)\navr_req.url_base(host, module)\n\navr_req['analyticsModule'].add(module)\navr_req['analyticsModule'].clear()\n\navr_req['reportFeatures'].add(metric_name, predicate, value)\navr_req['reportFeatures'].clear()\n\navr_req['entityFilters'].add(dimension_name, predicate, values)\navr_req['entityFilters'].clear()\n\navr_req['viewMetrics'].add(metric_name)\navr_req['viewMetrics'].clear()\n\navr_req['viewDimensions'].add(metric_name, order)\navr_req['viewDimensions'].clear()\n\navr_req['metricFilters'].add(metric_name, predicate, valu)\navr_req['metricFilters'].clear()\n\navr_req['sortByMetrics'].add(metric_name, orde)\navr_req['sortByMetrics'].clear()\n\navr_req['pagination'].add(num_results, skip_result)\navr_req['pagination'].clear()\n\navr_req['timeRange'].add(t_from, t_to)\navr_req['timeRange'].clear()\n\n\nAfter a request in constructed a REST API call is initiated with initiated with:\n\navr_req.post_and_response()\n\nThe response is a python dictionary data structure of the results as processed by json.loads\n\n\"\"\"\n\n\n\nfrom copy import deepcopy\nimport requests\nimport json\nimport sys\nimport time\nimport warnings\n\n__author__ = 'Mark Lloyd'\n__version__ = '1.0'\n\n# 05/24/2016\nimport json\nimport requests\nimport time\n\n\nclass BadDictElement(Exception):\n def __init__(self, key, value, expl):\n Exception.__init__(self, '{0} {1} {2} '.format(key, value, expl))\n\n\nclass BadTime(Exception):\n def __init__(self, variable, value):\n Exception.__init__(self, '{0} {1} should be 16 char decimal in microseconds '.format('a', 'b'))\n\n\nclass RequestFailure(Exception):\n def __init__(self, key, value):\n Exception.__init__(self, '{0} {1} '.format(key, value))\n\n\nclass analyticsModule(str):\n \"\"\"\n This class is tied to the structure of the parent class.\n parent() get's the parent object so we can make the string pseudo-mutable.\n accessed from within an avr request\n\n ['analyticsModule'].add(module)\n Adds a single string to analyticsModule element . If one exists it is replaced.\n\n ['analyticsModule'].clear()\n Send a null value to the analyticsModule element.\n\n See rest_avr.ShowAVRJsonApi for more details\n\n\n \"\"\"\n\n def parent(self, parent):\n self.parent = parent\n\n def add(self, module):\n \"\"\"\n avr_req.['analyticsModule'].add(module)\n Adds a single string to analyticsModule element . If one already exists it is replaced.\n This should be the same as the module string in avr_req.url_base.\n \"\"\"\n self.parent['analyticsModule'] = analyticsModule(module)\n self.parent['analyticsModule'].parent = self.parent\n\n def clear(self):\n \"\"\"\n avr_req.['analyticsModule'].add(module)\n replaces the analyticsModule mddule with a null string\n \"\"\"\n self.parent['analyticsModule'] = analyticsModule('')\n self.parent['analyticsModule'].parent = self.parent\n\n\nclass metricFilters(list):\n \"\"\"\n avr_req.['metricFilters'].add(metric_name, predicate, value)\n\n metric name is a string, value is an integer\n\n Valid predicates strings are ['OPERATOR_TYPE_EQUAL', 'OPERATOR_TYPE_NOT_EQUAL', 'OPERATOR_TYPE_GREATER_THAN',\n OPERATOR_TYPE_LOWER_THAN','OPERATOR_TYPE_GREATER_THAN_OR_EQUAL', 'OPERATOR_TYPE_LOWER_THAN_OR_EQUAL'])\n\n avr_req['metricFilters'].clear()\n Clears metricFilters elements\n\n See rest_avr.ShowAVRJsonApi for more details.\n\n \"\"\"\n\n def __init__(self):\n self.append([])\n self.valid_metric_predicate = (\n ['OPERATOR_TYPE_EQUAL', 'OPERATOR_TYPE_NOT_EQUAL', 'OPERATOR_TYPE_GREATER_THAN', 'OPERATOR_TYPE_LOWER_THAN',\n 'OPERATOR_TYPE_GREATER_THAN_OR_EQUAL', 'OPERATOR_TYPE_LOWER_THAN_OR_EQUAL'])\n\n def add(self, metric_name, predicate, value):\n \"\"\"\n avr_req.['metricFilters'].add(metric_name, predicate, value)\n\n metric name is a string, value is an integer\n\n Valid predicates strings are ['OPERATOR_TYPE_EQUAL', 'OPERATOR_TYPE_NOT_EQUAL', 'OPERATOR_TYPE_GREATER_THAN',\n OPERATOR_TYPE_LOWER_THAN','OPERATOR_TYPE_GREATER_THAN_OR_EQUAL', 'OPERATOR_TYPE_LOWER_THAN_OR_EQUAL']\n \"\"\"\n\n if type(value) is not int:\n raise BadDictElement(metric_name, value, 'value should be integer')\n\n if predicate in self.valid_metric_predicate:\n # first check if it is already there\n for metric in self[0]:\n if metric['metricName'] == metric_name:\n metric['predicate'] = predicate\n metric['value'] = value\n return 0\n # if it is not there then just add it.\n self[0].append({'metricName': metric_name, 'predicate': predicate, 'value': value})\n else:\n raise BadDictElement(metric_name, predicate, 'invalid predicate')\n\n def clear(self):\n \"\"\"\n avr_req['metricFilters'].clear()\n Clears metricFilters elements\n \"\"\"\n del self[0][:]\n\n\nclass entityFilters(list):\n \"\"\"\n avr_req.['entityFilters'].add(dimension_name, predicate, values):\n All values are strings\n valid predicate is 'OPERATOR_TYPE_EQUAL'\n\n ['entityFilters'].clear()\n Clears the entityFilters element\n\n See rest_avr.ShowJsonApi for more details\n \"\"\"\n\n def __init__(self):\n self.append([])\n\n def add(self, dimension_name, predicate, values):\n \"\"\"\n avr_req.['entityFilters'].add(dimension_name, predicate, values):\n All values are strings\n valid predicate is 'OPERATOR_TYPE_EQUAL'\n \"\"\"\n if predicate is 'OPERATOR_TYPE_EQUAL':\n # then loop throuth to see if the dimenson name already exists, if so replace\n for entity in self[0]:\n if entity['dimensionName'] == dimension_name:\n entity['predicate'] = predicate\n entity['values'] = values\n return 0\n # if it is not there then just add it.\n self[0].append({'dimensionName': dimension_name, 'predicate': predicate, 'values': values})\n\n else:\n raise BadDictElement(dimension_name, predicate, 'predicate must be OPERATOR_TYPE_EQUAL')\n\n def clear(self):\n \"\"\"\n ['entityFilters'].clear()\n Clears the entityFilters element\n \"\"\"\n del self[0][:]\n\n\nclass reportFeatures(list):\n \"\"\"\n avr_req.['reportFeatures'].add( feature)\n adds report feature string. Multiple features are permitted.\n\n ['reportFeatures'].clear()\n Clears the analyticsModule element.\n\n See rest_avr.ShowAVRJsonApi for more details.\n \"\"\"\n\n def add(self, feature):\n \"\"\"\n avr_req.['reportFeatures'].add( feature)\n adds report feature string. Multiple features are permitted\n .\"\"\"\n if feature not in self:\n self.append(feature)\n\n def clear(self):\n \"\"\"\n ['reportFeatures'].clear()\n Clears the entityFilters element\n \"\"\"\n del self[:]\n\n\nclass sortByMetrics(list):\n \"\"\"\n avr_req.['sortByMetrics'].add(metric_name, order)\n\n valid order names are 'ascending' and 'descending'\n sortByMetrics is optional in an AVR request.\n\n avr_req['sortByMetrics'].clear()\n Clears the sortByMetrics element.\n\n See rest_avr.ShowAVRJsonApi for more details.\n \"\"\"\n\n def __init__(self):\n self.metric_list = []\n\n def add(self, metric_name, order):\n if metric_name not in self.metric_list:\n self.append({'metricName': metric_name, 'order': order})\n self.metric_list.append(metric_name)\n\n def clear(self):\n \"\"\"\n ['sortByMetrics'].clear()\n Clears the sortByMetrics element\n \"\"\"\n del self[:]\n del self.metric_list[:]\n\n\nclass viewDimensions(list):\n \"\"\"\n avr_req.['viewDimensions'].add(dimension_name):\n adds view dimension, only one dimension is allowed\n add will replace element if it already exists\n\n avr_req['viewDimensions'].clear()\n Clears the viewDimensions element.\n\n See rest_avr.ShowAVRJsonApi for more details.\n \"\"\"\n\n def __init__(self):\n self.append([])\n self[0] = {}\n\n def add(self, dimension_name):\n \"\"\"\n avr_req.['viewDimensions'].add(dimension_name):\n adds view dimension string, only one dimension is allowed\n add will replace element if it already exists\n \"\"\"\n self[0]['dimensionName'] = dimension_name\n\n def clear(self, dimension_name):\n \"\"\"\n ['viewDimensions'].clear()\n Clears the viewDimensions element\n \"\"\"\n del self[0][:]\n\n\nclass viewMetrics(list):\n \"\"\"\n avr_req.['viewMetrics'].add(metric_name):\n appends metric_name string to list. The specification\n allows multiple view metric elements\n\n avr_req['viewMetrics'].clear()\n Clears the viewMetrics elements\n\n See rest_avr.ShowAVRJsonApi for more details.\n \"\"\"\n\n def __init__(self):\n self.metric_list = []\n\n def add(self, metric_name):\n \"\"\"\n avr_req.['viewMetrics'].add(metric_name):\n appends metric_name string to list. The specification\n allows multiple viewMetric elements\n \"\"\"\n\n if metric_name not in self.metric_list:\n self.append({'metricName': metric_name})\n self.metric_list.append(metric_name)\n\n def clear(self):\n \"\"\"\n ['viewMetrics'].clear()\n Clears the viewMetrics elements\n \"\"\"\n del self[:]\n del self.metric_list[:]\n\n\nclass timeRange(dict):\n \"\"\"\n avr_req.['timeRange'].add( t_from, t_to)\n both values are 16 digit numeric value in microseconds\n of unix/linux time. t_to is optional and can be replace by None\n\n timeRange is an optional.\n\n avr_req['timeRange'].clear()\n Clears the timeRange elements\n\n See rest_avr.ShowAVRJsonApi for more details.\n \"\"\"\n\n def add(self, t_from, t_to):\n \"\"\"\n avr_req.['timeRange'].add( t_from, t_to)\n both values are 16 digit numeric value in microseconds\n of unix/linux time. t_to is optional and can be replace by None\n\n timeRange is optional.\n \"\"\"\n if type(t_from) is long and len(str(t_from)) == 16:\n self['from'] = t_from\n else:\n raise BadTime(t_from + \" is 16 digit numeric value in microseconds\")\n\n if t_to != '' and t_to != 0 and t_to != None:\n if type(t_to) is long and len(str(t_from)) == 16:\n self['to'] = t_to\n else:\n raise BadTime(t_to + \" is 16 digit numeric value in microseconds\")\n else:\n if 'to' in self.keys():\n del self['to']\n\n def clear(self):\n \"\"\"\n ['timeRange'].clear()\n Clears the timeRange element\n \"\"\"\n del self[:]\n\n\nclass pagination(dict):\n \"\"\"\n avr_req.['pagination'].add(num_results, skip_results)\n both are integer values.\n\n avr_req['pagination'].clear()\n Clears the pagination elements\n\n See rest_avr.ShowAVRJsonApi for more details.\n \"\"\"\n\n def add(self, num_results, skip_results):\n \"\"\"\n avr_req.['pagination'].add(num_results, skip_results)\n both arguments are integers.\n \"\"\"\n if type(num_results) is int:\n self['numberOfResults'] = num_results\n else:\n raise BadDictElement('number of Results ', num_results, 'must be integer')\n if type(skip_results) is int:\n self['skipResults'] = skip_results\n else:\n raise BadDictElement('skipResults ', skip_results, 'must be integer')\n\n def clear(self):\n \"\"\"\n ['pagination'].clear()\n Clears the pagination element\n \"\"\"\n del self[:]\n\n\nclass avr_resp(dict):\n \"\"\"\n python response error is applicable.\n \"\"\"\n\n def __init__(self):\n self.error_layer = None\n self.error_code = None\n self.error_text = None\n\nclass avr_req(dict):\n \"\"\"\n The main class for rest_avr.\n\n avr_req contains a dictionary that maps to the elements of a Icontrol REST AVR request along with capability of\n posting that request and receiving a response.\n\n The dictionary values are object instances of python classes that correspond to the the JSON values of the\n object's name/value pair.\n\n Each value has two public methods:\n\n avr_req.['objectName']add(): adds an element to the appropriate object with type checking.\n If an element allows more then one instance the add function will append the element\n If an element allows only one instance the add function will replace the element\n\n avr_req.['objectName'].clear()r: clears all elements in the object.\n\n printing rest_avr.ShowAVRJsonApi provides documentation for the AVR JASON elements. Further documentation is\n available on devcentral.f5.com\n\n To post an AVR Rest request there are two functions to populate the HTTP/HTTPS request.\n\n avr_req.auth(user, passw):\n provides the username and password\n avr_req.url_base(host, module)\n provides the host and the bigip module AVR queries to construct the URL to make the request.\n\n Then to post the request and return results in a python representation of the JSON response.\n\n avr_req.post_and_response()\n\n \"\"\"\n\n def __init__(self):\n self['analyticsModule'] = analyticsModule()\n self['analyticsModule'].parent = self\n self['pagination'] = pagination()\n self['metricFilters'] = metricFilters()\n self['entityFilters'] = entityFilters()\n self['reportFeatures'] = reportFeatures()\n self['sortByMetrics'] = sortByMetrics()\n self['viewDimensions'] = viewDimensions()\n self['viewMetrics'] = viewMetrics()\n self['timeRange'] = timeRange()\n\n self.avr_session = requests.session()\n self.avr_session.verify = False\n self.avr_session.headers.update({'Content-Type': 'application/json'})\n\n # for multiple queued request handling.\n self.req_queue = []\n self.generate_id = None\n self.done = None\n self.result = None\n self.num_requests = 0\n self.res_queue = []\n\n def post_and_response(self):\n \"\"\"\n returns a python representation of the json response to the request.\n failure returns array ['ERROR','component',error]\n \"\"\"\n\n warnings.filterwarnings(\"ignore\")\n self.generate_request = self.avr_session.post(self.req_url_base + \"/generate-report/\",\n data=json.dumps(self))\n self.generate_request_py = json.loads(self.generate_request.text)\n self.result_guid = self.generate_request_py['id']\n self.results_status_url = self.req_url_base + \"/generate-report/\" + self.result_guid + \"/?$select=status,reportResultsLink\"\n self.results_url = self.req_url_base + \"/report-results/\" + self.result_guid\n self.sleeptime = .5\n for i in range(5):\n time.sleep(self.sleeptime)\n self.sleeptime *= 2 # double backoff period each time.\n\n self.status_results_json = self.avr_session.get(self.results_status_url)\n self.status_results = json.loads(self.status_results_json.text)\n\n if self.status_results['status'] == 'FAILED':\n self.result = avr_resp()\n self.result_error_layer = 'REST'\n self.result_error_code = self.status_results['status']\n self.result.error_text = self.status_results\n\n if self.status_results['status'] == 'FINISHED':\n self.raw_results_url = self.status_results['reportResultsLink']\n self.results_url = self.raw_results_url.replace('localhost', self.host_name)\n self.results = self.avr_session.get(self.results_url)\n\n if self.results.status_code == 200:\n self.result = avr_resp()\n self.result.update(json.loads(self.results.text))\n return self.result\n else:\n self.result = avr_resp()\n self.result.error_layer = 'HTTP'\n self.result.error_code = self.results.status_code\n self.result.error_text = self.results\n return self.result\n\n else:\n\n continue\n\n self.result = avr_resp()\n self.result.error_layer = 'REST_AVR'\n self.result.error_code = '408'\n self.result.error_text = 'TIMEOUT'\n\n\n def auth(self, user, passw):\n \"\"\"\n avr_req.auth(user, passw):\n username and password\n \"\"\"\n self.avr_session.auth = (user, passw)\n\n def url_base(self, host, module):\n \"\"\"\n avr_req.url_base(host, module)\n host and bigip module AVR queries to construct the URL to make the request.\n \"\"\"\n self.host_name = host\n self.req_url_base = 'https://%s/mgmt/tm/analytics/%s' % (host, module)\n self.module_py = {'analyticsModule': module}\n\n def add_to_queue(self):\n \"adds request as currently constructed to queue\"\n self.req_queue.append(deepcopy(self))\n\n def clear_queue(self):\n \"\"\"\"\n clears request queue\n \"\"\"\n del self.req_queue[:]\n\n def post_and_response_queue(self):\n \"\"\"\n posts and sends response to from queue of requests.\n \"\"\"\n warnings.filterwarnings(\"ignore\")\n for req in self.req_queue:\n req.generate_request = req.avr_session.post(req.req_url_base + \"/generate-report/\",\n data=json.dumps(req))\n req.generate_request_py = json.loads(req.generate_request.text)\n req.generate_id = (req.generate_request_py['id'])\n req.results_status_url = self.req_url_base + \"/generate-report/\" + req.generate_id + \"/?$select=status,reportResultsLink\"\n\n self.sleeptime = .5\n self.num_requests = len(self.req_queue)\n\n for i in range(5):\n\n for req in self.req_queue:\n\n if req.done is None:\n\n time.sleep(self.sleeptime)\n self.sleeptime *= 2 # double backoff period each time.\n req.status_results_json = req.avr_session.get(req.results_status_url)\n req.status_results = json.loads(req.status_results_json.text)\n\n if req.status_results['status'] == 'FAILED':\n req.result = avr_resp()\n req.result_error['layer'] = 'REST'\n req.result_error['error'] = req.status_results['status']\n req.result_error['text'] = req.status_results\n if req.status_results['status'] == 'FINISHED':\n req.raw_results_url = req.status_results['reportResultsLink']\n req.results_url = req.raw_results_url.replace('localhost', self.host_name)\n req.results = self.avr_session.get(req.results_url)\n if req.results.status_code == 200:\n req.result = avr_resp()\n req.result.update(json.loads(req.results.text))\n req.done = True\n self.res_queue.append(req.result)\n self.num_requests -= 1\n\n else:\n\n req.result = avr_resp()\n req.result_error.layer = 'HTTP'\n req.result_error.code = req.results.status_code\n req.result_error.text = req.results\n self.res_queue.append(req.result)\n if i == 5:\n if req.result == False:\n req.result = avr_resp()\n req.result.error_layer = 'REST_AVR'\n req.result.error_error = '408'\n req.result.error_text = 'TIMEOUT'\n\n\n if self.num_requests == 0:\n break\n\n\n\n return self.res_queue\n\n\nShowAVRJsonApi = \"\"\"\nreportFeatures\n--------------\nSpecifies the kind of information that appears in a\nresponse from AVR. You may specify one or more of the\nfollowing values:\n\nexisting-entities\ntime-aggregated\ntime-series\nentities-count\n\nviewDimensions\n--------------\nSpecifies the dimensions for which to calculate a report,\nsuch as:\n\n{\"dimensionName\": \"domain-name\"}\n\nYou may only specify a single dimension. You may omit\nthis field in a report generation request.\n\nviewMetrics\n-----------\nSpecifies the list of metrics by which to sort results, such\nas:\n\n{ \"metricName\": \"average-tps\" },\n{ \"metricName\": \"transactions\" }\n\nIf you specify either time-aggregated or\ntime-series features, you must specify one metric in\na report generation request.\n\nsortByMetrics\n--------------\nSpecifies the list of metrics to sort by, such as:\n[{ metricName: \"average-tps\", order:\"descending\" } ]\n\nValid values are ascending and descending. Sorting\nonly applies to the time-aggregated feature. You do\nnot need to specify this field in a report generation request.\n\ntimeRange\n---------\nSpecifies the time range, in microseconds, for which to\ncalculate a report, such as:\n\n{\"from\": 1410420888000000, \"to\": 1410424488000000 }\n\nYou do not need to specify this field in a report generation\nrequest.\n\nentityFilters\n=============\nSpecifies the entities and values for which to calculate a\nreport. You can specify a single entity with a second level\nof dimension filters that describe an aspect of the entity.\nIf you specify multiple entity types, the results include\nonly the entities that match all of the criteria. You do not\nneed to specify this field in a report generation request.\nThe following snippet contains two entities with\ncorresponding values:\n\n[[{\n\"dimensionName\" : \"virtual\",\n\"predicate\": \"OPERATOR_TYPE_EQUAL\",\n\"values : [\"phpAuction_VS_1\"] },\n{\n\"dimensionName : \"response-code\",\n\"predicate\": \"OPERATOR_TYPE_EQUAL\",\n\"values\" : [\"200\"] }\n]]\n\nmetricFilters\n-------------\nSpecifies the metric filters for which to calculate a report,\nsuch as:\n\n[{ \"metricName\": \"transactions\",\n\"predicate\" :\nmetricFilters\n\"OPERATOR_TYPE_GREATER_THAN\" \"value\":\n100 }]\n\nYou do not need to specify this field in a report generation\nrequest. For the existing-entities feature, AVR\nsupports the OPERATOR_TYPE_LIKE predicate. AVR also\nsupports the following predicates:\n\nOPERATOR_TYPE_EQUAL\nOPERATOR_TYPE_NOT_EQUAL\nOPERATOR_TYPE_GREATER_THAN\nOPERATOR_TYPE_LOWER_THAN\nOPERATOR_TYPE_GREATER_THAN_OR_EQUAL\nOPERATOR_TYPE_LOWER_THAN_OR_EQUAL\n\npagination\n----------\nSpecifies the number of results to return, and the number\nof results to skip, such as:\n\n{ numberOfResults : 10, skipResults : 10}\n\nTo see the second set of ten results, use the example\nshown here. AVR does not implement the OData query\nparameters top or skip. In order to see a specific set of\nresults, you must set the number of results to return and\nthen determine how many results to skip. You do not need\nto specify this field in a report generation request.\n\"\"\" Tested this on version: 12.0","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"27262","kudosSumWeight":0,"repliesCount":1,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:334446":{"__typename":"Conversation","id":"conversation:334446","topic":{"__typename":"ForumTopicMessage","uid":334446},"lastPostingActivityTime":"2024-11-11T15:22:46.956-08:00","solved":false},"User:user:285832":{"__typename":"User","uid":285832,"login":"teoiovine","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-4.svg?time=0"},"id":"user:285832"},"ForumTopicMessage:message:334446":{"__typename":"ForumTopicMessage","subject":"Microsoft 365 IP Steering python script","conversation":{"__ref":"Conversation:conversation:334446"},"id":"message:334446","revisionNum":1,"uid":334446,"depth":0,"board":{"__ref":"Forum:board:TechnicalForum"},"author":{"__ref":"User:user:285832"},"metrics":{"__typename":"MessageMetrics","views":141},"postTime":"2024-09-16T12:50:27.869-07:00","lastPublishTime":"2024-09-16T12:50:27.869-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Hello! Hola! I have created a small and rudimentary script that generates a datagroup with MS 365 IPv4 and v6 addresses to be used by an iRule or policy. There are other scripts that solve this same issue but either they were: based on iRulesLX, which forces you to enable iRuleLX only for this, and made me run into issues when upgrading (memory table got filled with nonsense) based on the XML version of the list, which MS changed to a JSON file. This script is a super simple bash script that calls another super simple python file, and a couple of helper files. The biggest To Do are: Add a more secure approach to password usage. Right now, it is stored in a parameters file locked away with permissions. There should be a better way. Add support for URLs. You can find the contents here: https://github.com/teoiovine-novared/fetch-office365/tree/main I appreciate advice, (constructive) criticism and questions all the same! Thank you for your time. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"986","kudosSumWeight":1,"repliesCount":3,"readOnly":true,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:336355":{"__typename":"Conversation","id":"conversation:336355","topic":{"__typename":"TkbTopicMessage","uid":336355},"lastPostingActivityTime":"2024-11-11T15:21:29.350-08:00","solved":false},"TkbTopicMessage:message:336355":{"__typename":"TkbTopicMessage","subject":"Microsoft 365 IP Steering python Script","conversation":{"__ref":"Conversation:conversation:336355"},"id":"message:336355","revisionNum":1,"uid":336355,"depth":0,"board":{"__ref":"Tkb:board:codeshare"},"author":{"__ref":"User:user:285832"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":61},"postTime":"2024-11-11T15:21:29.350-08:00","lastPublishTime":"2024-11-11T15:21:29.350-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Hello! Hola! I have created a small and rudimentary script that generates a datagroup with MS 365 IPv4 and v6 addresses to be used by an iRule or policy. There are other scripts that solve this same issue but either they were: based on iRulesLX which forces you to enable iRuleLX only for this, and made me run into issues when upgrading (memory table got filled with nonsense) based on the XML version of the list which MS changed to a JSON file. This script is a super simple bash script that calls another super simple python file, and a couple of helper files. The biggest To Do are: Add a more secure approach to password usage. Right now, it is stored in a parameters file locked away with permissions. There should be a better way. Add support for URLs. You can find the contents here: https://github.com/teoiovine-novared/fetch-office365/tree/main I appreciate advice, (constructive) criticism and questions all the same! Thank you for your time. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"982","kudosSumWeight":0,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:333178":{"__typename":"Conversation","id":"conversation:333178","topic":{"__typename":"TkbTopicMessage","uid":333178},"lastPostingActivityTime":"2024-09-11T08:23:19.422-07:00","solved":false},"User:user:275883":{"__typename":"User","uid":275883,"login":"Tony_Marfil","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0yNzU4ODMtQ2o3aUZ6?image-coordinates=0%2C0%2C3022%2C3022"},"id":"user:275883"},"TkbTopicMessage:message:333178":{"__typename":"TkbTopicMessage","subject":"VIPTest: Rapid Application Testing for F5 Environments","conversation":{"__ref":"Conversation:conversation:333178"},"id":"message:333178","revisionNum":4,"uid":333178,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:275883"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" VIPTest is a Python-based tool for efficiently testing multiple URLs in F5 environments, allowing quick assessment of application behavior before and after configuration changes. It supports concurrent processing, handles various URL formats, and provides detailed reports on HTTP responses, TLS versions, and connectivity status, making it useful for migrations and routine maintenance. ","introduction":"","metrics":{"__typename":"MessageMetrics","views":776},"postTime":"2024-08-20T05:00:00.039-07:00","lastPublishTime":"2024-09-04T09:43:48.631-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" The Motivation Behind VIPTest \n As an F5 Solutions Architect, I noticed a recurring challenge with prospective customers: there was no quick way to \"grade\" the success of migrating from their current environment to F5 solutions. This gap made it difficult to quickly identify and address problem areas. To solve this, I developed VIPTest - a tool designed as a convenience for anyone considering moving their applications from a different vendor solution (e.g., Citrix NetScaler) to F5. \n However, VIPTest's utility extends far beyond migration scenarios. It can be used in any environment where you introduce a change and need an automated process to assess the success of these changes. Whether you're upgrading software, modifying configurations, or performing routine maintenance, VIPTest provides a rapid, comprehensive snapshot of your application landscape. \n F5's Application Services and Security Solutions \n Before we dive into VIPTest, let's briefly explore F5's three new families of Application Services and Security solutions: \n \n \n F5 Distributed Cloud (XC): A SaaS-based security, networking, and application management solution that provides multi-cloud networking, web application and API protection, and edge-based computing. \n \n \n BIG-IP Next: The next generation of F5's flagship product, offering advanced traffic management, security, and analytics in a more flexible, software-first architecture. \n \n \n NGINX: A suite of cloud native technologies that provide API gateway, reverse proxy, and application security, known for its high performance and scalability. \n \n \n With VIPTest, you can confidently introduce changes to any of these solutions and quickly assess their impact. It's equally valuable for evaluating initial migrations and for ongoing operational changes within the same solution. \n The Problem VIPTest Solves \n Customers often lack a quick, automated way to assess the impact of environment changes on their applications. VIPTest addresses this by providing: \n \n Fast, concurrent testing of multiple URLs \n Pre and post-change comparisons \n Detection of improvements (e.g., TLS upgrades, HTTP/1.1 to HTTP/2 upgrades) and issues (e.g., broken connectivity) \n Identification of deprecated applications so you don't wast time testing 'dead' URLs \n Rapid assessment when migrating from another vendor's solution, such as Citrix NetScaler \n A simple mechanism to target just a staging environment during testing by overriding system DNS with static IP entries \n \n Let's explore how VIPTest works and how you can leverage it in your F5 environment. \n How VIPTest Works \n VIPTest, available on GitHub, accepts a CSV file containing URLs and IP addresses. It then: \n \n Validates URLs and IP addresses \n Performs HTTP/HTTPS requests \n Checks TLS versions and ciphers \n Tests connectivity (ping and telnet) \n Reports results for easy comparison \n \n Key Features \n \n \n Concurrent Processing: VIPTest uses Python's multiprocessing module to test as many URLs simultaneously as your client machine can support. On my modest Intel 10th gen / 6 Core laptop, I can test 1000 URLs in less than one minute. \n \n \n Flexible URL Handling: It supports various URL formats, including: \n \n Full URLs (http://example.com) \n IP addresses with ports (192.168.1.1:80) \n URLs with custom ports (https://example.com:8443) \n \n \n \n Detailed Reporting: VIPTest provides information on: \n \n HTTP response codes \n TLS versions and ciphers \n IP resolution \n Connectivity status \n \n \n \n VIPTest works with Linux, Windows (WSL2), and MacOS (Zsh using homebrew). \n Setting Up VIPTest \n See README.md for full installation and useage details. \n \n \n Ensure you have Python 3.8+ installed: \n python3 --version \n \n Create a virtual environment: \n python3 -m venv myenv\nsource myenv/bin/activate \n \n Clone the VIPTest repository: \n git clone https://github.com/tmarfil/viptest.git\ncd viptest \n \n Install requirements: \n pip3 install -r requirements.txt \n \n Make viptest.py executable: \n chmod +x viptest.py \n \n Using VIPTest \n \n \n Create a CSV file with your URLs (see README.md for format details). \n \n \n Run VIPTest: \n viptest.py --csv your_file.csv -c 50 \n This tests URLs concurrently using 50 processes. \n \n \n Save the output: \n viptest.py --csv your_file.csv -c 50 > pre_change_results.log \n \n Make your environment changes. \n \n \n Run VIPTest again: \n viptest.py --csv your_file.csv -c 50 > post_change_results.log \n \n Compare results: \n diff pre_change_results.log post_change_results.log \n \n The Power of HTTPX \n VIPTest leverages the HTTPX client for Python3: \n \n HTTP/2 Support: Enables testing of modern application stacks. \n Automatic Retries: Improves reliability in unstable network conditions. \n Connection Pooling: Enhances performance for multiple requests to the same host. \n Timeout Handling: Prevents hung requests from slowing down the entire test suite. \n \n Concurrent Testing with Multiprocessing \n The Python multiprocessing package is crucial for VIPTest's performance. Here's how it works: \n \n The URL list is divided into chunks. \n Each chunk is processed by a separate Python process. \n Results are collected in a shared queue. \n \n This approach allows VIPTest to test one thousand URLs in less than one minute. The Python code implements this using: \n if args.concurrent:\n chunk_size = len(urls) // args.concurrent\n chunks = list(chunked_iterable(urls, chunk_size))\n processes = []\n for chunk in chunks:\n p = multiprocessing.Process(target=process_urls, args=(chunk, output_queue, counter))\n processes.append(p)\n p.start() \n Automating with CI/CD \n Integrating VIPTest into your CI/CD pipeline ensures consistent testing. Here's a basic GitHub Actions workflow: \n name: VIPTest\n\non:\n push:\n branches: [ main ]\n pull_request:\n branches: [ main ]\n\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v2\n - name: Set up Python\n uses: actions/setup-python@v2\n with:\n python-version: '3.12'\n - name: Install dependencies\n run: |\n python -m pip install --upgrade pip\n pip install -r requirements.txt\n - name: Run VIPTest\n run: |\n viptest.py --csv testfile.csv -c 50 > test_results.log\n - name: Upload results\n uses: actions/upload-artifact@v2\n with:\n name: test-results\n path: test_results.log \n This workflow runs VIPTest on every push to the main branch or pull request, saving the results as an artifact. \n For GitLab users, a similar pipeline can be created using .gitlab-ci.yml: \n stages:\n - test\n\nviptest:\n stage: test\n image: python:3.12\n script:\n - pip install -r requirements.txt\n - viptest.py --csv testfile.csv -c 50 > test_results.log\n artifacts:\n paths:\n - test_results.log \n Conclusion \n VIPTest empowers F5 customers to confidently make environment changes across all F5 solutions - from Distributed Cloud (XC) to BIG-IP Next and NGINX. By providing quick, comprehensive application testing, it reduces risk and improves the success rate of migrations, upgrades, and day-to-day operations. Whether you're moving from a competitor's solution or optimizing your current F5 setup, VIPTest is an invaluable tool in your toolkit. \n Start using VIPTest today to ensure your applications stay healthy through every environment change! ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"7381","kudosSumWeight":5,"repliesCount":2,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:290328":{"__typename":"Conversation","id":"conversation:290328","topic":{"__typename":"TkbTopicMessage","uid":290328},"lastPostingActivityTime":"2024-08-29T03:26:38.635-07:00","solved":false},"TkbTopicMessage:message:290328":{"__typename":"TkbTopicMessage","subject":"Demystifying iControl REST Part 7 - Understanding Transactions","conversation":{"__ref":"Conversation:conversation:290328"},"id":"message:290328","revisionNum":2,"uid":290328,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:51154"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":3253},"postTime":"2016-08-12T14:30:00.000-07:00","lastPublishTime":"2023-06-05T22:49:39.204-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" iControl REST. It’s iControl SOAP’s baby, brother, introduced back in TMOS version 11.4 as an early access feature but released fully in version 11.5. Several articles on basic usage have been written about the rest interface so the intent here isn’t basic use, but rather to demystify some of the finer details of using the API. \n\n A few months ago, a question in Q&A from community member spirrello asking how to update a tcp profile on a virtual. He was using bigsuds, the python wrapper for the soap interface. For the rest interface on this particular object, this is easy; just use the put method and supply the payload mapping the updated profile. But for soap, this requires a transaction. There are some changes to BIG-IP via the rest interface, however, like updating an ssl cert or key, that likewise will require a transaction to accomplish. In this article, I’ll show you how to use transactions with the rest interface. \n\n The Fine Print \n\n From the iControl REST user guide, the life cycle of a transaction progresses through three phases: \n\n Creation - This phase occurs when the transaction is created using a POST command. Modification - This phase occurs when commands are added to the transaction, or changes are made to the sequence of commands in the transaction. Commit - This phase occurs when iControl REST runs the transaction. \n\n To create a transaction, post to /tm/transaction \n\n \n POST https://192.168.25.42/mgmt/tm/transaction\n\n {}\n\n Response:\n\n {\n \"transId\":1389812351,\n \"state\":\"STARTED\",\n \"timeoutSeconds\":30,\n \"kind\":\"tm:transactionstate\",\n \"selfLink\":\"https://localhost/mgmt/tm/transaction/1389812351?ver=11.5.0\"\n } \n\n Note the transId, the state, and the timeoutSeconds. You'll need the transId to add or re-sequence commands within the transaction, and the transaction will expire after 30 seconds if no commands are added. You can list all transactions, or the details of a specific transaction with a get request. \n\n \n GET https://192.168.25.42/mgmt/tm/transaction\n GET https://192.168.25.42/mgmt/tm/transaction/transId \n\n To add a command to the transaction, you use the normal method uris, but include the X-F5-REST-Coordination-Id header. This example creates a pool with a single member. \n\n \n POST https://192.168.25.42/mgmt/tm/ltm/pool\n X-F5-REST-Coordination-Id:1389812351\n {\n \"name\":\"tcb-xact-pool\",\n \"members\": [ {\"name\":\"192.168.25.32:80\",\"description\":\"First pool for transactions\"} ]\n } \n\n Not a great example because there is no need for a transaction here, but we'll roll with it! There are several other option methods for interrogating the transaction itself, see the user guide for details. Now we can commit the transaction. To do that, you reference the transaction id in the URI, remove the X-F5-REST-Coordination-Id header and use the patch method with payload key/value state: VALIDATING . \n\n \n PATCH https://localhost/mgmt/tm/transaction/1389812351\n { \"state\":\"VALIDATING\" } \n\n That's all there is to it! Now that you've seen the nitty gritty details, let's take a look at some code samples. \n\n Roll Your Own \n\n In this example, I am needing to update and ssl key and certificate. If you try to update the cert or the key, it will complain that they do not match, so you need to update both at the same time. Assuming you are writing all your code from scratch, this is all it takes in python. Note on line 21 I post with an empty payload, and then on line 23, I add the header with the transaction id. I make my modifications and then in line 31, I remove the header, and finally on line 32, I patch to the transaction id with the appropriate payload. \n\n \n import json\n import requests\n\n btx = requests.session()\n btx.auth = (f5_user, f5_password)\n btx.verify = False\n btx.headers.update({'Content-Type':'application/json'})\n urlb = 'https://{0}/mgmt/tm'.format(f5_host)\n\n domain = 'mydomain.local_sslobj'\n chain = 'mychain_sslobj\n\n try:\n key = btx.get('{0}/sys/file/ssl-key/~Common~{1}'.format(urlb, domain))\n cert = btx.get('{0}/sys/file/ssl-cert/~Common~{1}'.format(urlb, domain))\n chain = btx.get('{0}/sys/file/ssl-cert/~Common~{1}'.format(urlb, 'chain'))\n\n if (key.status_code == 200) and (cert.status_code == 200) and (chain.status_code == 200):\n\n # use a transaction\n txid = btx.post('{0}/transaction'.format(urlb), json.dumps({})).json()['transId']\n # set the X-F5-REST-Coordination-Id header with the transaction id\n btx.headers.update({'X-F5-REST-Coordination-Id': txid})\n\n # make modifications\n modkey = btx.put('{0}/sys/file/ssl-key/~Common~{1}'.format(urlb, domain), json.dumps(keyparams))\n modcert = btx.put('{0}/sys/file/ssl-cert/~Common~{1}'.format(urlb, domain), json.dumps(certparams))\n modchain = btx.put('{0}/sys/file/ssl-cert/~Common~{1}'.format(urlb, 'le-chain'), json.dumps(chainparams))\n\n # remove header and patch to commit the transaction\n del btx.headers['X-F5-REST-Coordination-Id']\n cresult = btx.patch('{0}/transaction/{1}'.format(urlb, txid), json.dumps({'state':'VALIDATING'})).json() \n\n A Little Help from a Friend \n\n The f5-common-python library was released a few months ago to relieve you of a lot of the busy work with building requests. This is great, especially for transactions. To simplify the above code just to the transaction steps, consider: \n\n \n # use a transaction\n txid = btx.post('{0}/transaction'.format(urlb), json.dumps({})).json()['transId']\n # set the X-F5-REST-Coordination-Id header with the transaction id\n btx.headers.update({'X-F5-REST-Coordination-Id': txid})\n\n# do stuff here\n\n # remove header and patch to commit the transaction\n del btx.headers['X-F5-REST-Coordination-Id']\n cresult = btx.patch('{0}/transaction/{1}'.format(urlb, txid), json.dumps({'state':'VALIDATING'})).json() \n\n With the library, it's simplified to: \n\n \n tx = b.tm.transactions.transaction\n with TransactionContextManager(tx) as api:\n # do stuff here\n api.do_stuff \n\n Yep, it's that simple. So if you haven't checked out the f5-common-python library, I highly suggest you do! I'll be writing about how to get started using it next week, and perhaps a follow up on how to contribute to it as well, so stay tuned! ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"6407","kudosSumWeight":2,"repliesCount":9,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"CachedAsset:text:en_US-components/community/Navbar-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/Navbar-1744046271000","value":{"community":"Community Home","inbox":"Inbox","manageContent":"Manage Content","tos":"Terms of Service","forgotPassword":"Forgot Password","themeEditor":"Theme Editor","edit":"Edit Navigation Bar","skipContent":"Skip to content","migrated-link-9":"Groups","migrated-link-7":"Technical Articles","migrated-link-8":"DevCentral News","migrated-link-1":"Technical Forum","migrated-link-10":"Community Groups","migrated-link-2":"Water Cooler","migrated-link-11":"F5 Groups","Common-external-link":"How Do I...?","migrated-link-0":"Forums","article-series":"Article Series","migrated-link-5":"Community Articles","migrated-link-6":"Articles","security-insights":"Security Insights","migrated-link-3":"CrowdSRC","migrated-link-4":"CodeShare","migrated-link-12":"Events","migrated-link-13":"Suggestions"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarHamburgerDropdown-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarHamburgerDropdown-1744046271000","value":{"hamburgerLabel":"Side Menu"},"localOverride":false},"CachedAsset:text:en_US-components/community/BrandLogo-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/BrandLogo-1744046271000","value":{"logoAlt":"Khoros","themeLogoAlt":"Brand Logo"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarTextLinks-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarTextLinks-1744046271000","value":{"more":"More"},"localOverride":false},"CachedAsset:text:en_US-components/authentication/AuthenticationLink-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/authentication/AuthenticationLink-1744046271000","value":{"title.login":"Sign In","title.registration":"Register","title.forgotPassword":"Forgot Password","title.multiAuthLogin":"Sign In"},"localOverride":false},"CachedAsset:text:en_US-components/nodes/NodeLink-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/nodes/NodeLink-1744046271000","value":{"place":"Place {name}"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagSubscriptionAction-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagSubscriptionAction-1744046271000","value":{"success.follow.title":"Following Tag","success.unfollow.title":"Unfollowed Tag","success.follow.message.followAcrossCommunity":"You will be notified when this tag is used anywhere across the community","success.unfollowtag.message":"You will no longer be notified when this tag is used anywhere in this place","success.unfollowtagAcrossCommunity.message":"You will no longer be notified when this tag is used anywhere across the community","unexpected.error.title":"Error - Action Failed","unexpected.error.message":"An unidentified problem occurred during the action you took. Please try again later.","buttonTitle":"{isSubscribed, select, true {Unfollow} false {Follow} other{}}","unfollow":"Unfollow"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/QueryHandler-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/QueryHandler-1744046271000","value":{"title":"Query Handler"},"localOverride":false},"Category:category:top":{"__typename":"Category","id":"category:top","nodeType":"category"},"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarDropdownToggle-1744046271000","value":{"ariaLabelClosed":"Press the down arrow to open the menu"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageListTabs-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageListTabs-1744046271000","value":{"mostKudoed":"{value, select, IDEA {Most Votes} other {Most Likes}}","mostReplies":"Most Replies","mostViewed":"Most Viewed","newest":"{value, select, IDEA {Newest Ideas} OCCASION {Newest Events} other {Newest Topics}}","newestOccasions":"Newest Events","mostRecent":"Most Recent","noReplies":"No Replies Yet","noSolutions":"No Solutions Yet","solutions":"Solutions","mostRecentUserContent":"Most Recent","trending":"Trending","draft":"Drafts","spam":"Spam","abuse":"Abuse","moderation":"Moderation","tags":"Tags","PAST":"Past","UPCOMING":"Upcoming","sortBymostRecent":"Sort By Most Recent","sortBymostRecentUserContent":"Sort By Most Recent","sortBymostKudoed":"Sort By Most Likes","sortBymostReplies":"Sort By Most Replies","sortBymostViewed":"Sort By Most Viewed","sortBynewest":"Sort By Newest Topics","sortBynewestOccasions":"Sort By Newest Events","otherTabs":" Messages list in the {tab} for {conversationStyle}","guides":"Guides","archives":"Archives"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageView/MessageViewInline-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageView/MessageViewInline-1744046271000","value":{"bylineAuthor":"{bylineAuthor}","bylineBoard":"{bylineBoard}","anonymous":"Anonymous","place":"Place {bylineBoard}","gotoParent":"Go to parent {name}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Pager/PagerLoadMore-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Pager/PagerLoadMore-1744046271000","value":{"loadMore":"Show More"},"localOverride":false},"CachedAsset:text:en_US-components/customComponent/CustomComponent-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/customComponent/CustomComponent-1744046271000","value":{"errorMessage":"Error rendering component id: {customComponentId}","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/OverflowNav-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/OverflowNav-1744046271000","value":{"toggleText":"More"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserLink-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserLink-1744046271000","value":{"authorName":"View Profile: {author}","anonymous":"Anonymous"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageSubject-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageSubject-1744046271000","value":{"noSubject":"(no subject)"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBody-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBody-1744046271000","value":{"showMessageBody":"Show More","mentionsErrorTitle":"{mentionsType, select, board {Board} user {User} message {Message} other {}} No Longer Available","mentionsErrorMessage":"The {mentionsType} you are trying to view has been removed from the community.","videoProcessing":"Video is being processed. Please try again in a few minutes.","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageTime-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageTime-1744046271000","value":{"postTime":"Published: {time}","lastPublishTime":"Last Update: {time}","conversation.lastPostingActivityTime":"Last posting activity time: {time}","conversation.lastPostTime":"Last post time: {time}","moderationData.rejectTime":"Rejected time: {time}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeIcon-1744046271000","value":{"contentType":"Content Type {style, select, FORUM {Forum} BLOG {Blog} TKB {Knowledge Base} IDEA {Ideas} OCCASION {Events} other {}} icon"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageUnreadCount-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageUnreadCount-1744046271000","value":{"unread":"{count} unread","comments":"{count, plural, one { unread comment} other{ unread comments}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageViewCount-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageViewCount-1744046271000","value":{"textTitle":"{count, plural,one {View} other{Views}}","views":"{count, plural, one{View} other{Views}}"},"localOverride":false},"CachedAsset:text:en_US-components/kudos/KudosCount-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/kudos/KudosCount-1744046271000","value":{"textTitle":"{count, plural,one {{messageType, select, IDEA{Vote} other{Like}}} other{{messageType, select, IDEA{Votes} other{Likes}}}}","likes":"{count, plural, one{like} other{likes}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageRepliesCount-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageRepliesCount-1744046271000","value":{"textTitle":"{count, plural,one {{conversationStyle, select, IDEA{Comment} OCCASION{Comment} other{Reply}}} other{{conversationStyle, select, IDEA{Comments} OCCASION{Comments} other{Replies}}}}","comments":"{count, plural, one{Comment} other{Comments}}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1744046271000":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserAvatar-1744046271000","value":{"altText":"{login}'s avatar","altTextGeneric":"User's avatar"},"localOverride":false}}}},"page":"/tags/TagPage/TagPage","query":{"tagName":"python"},"buildId":"-gVUpXaWnPcjlrLJZ92B7","runtimeConfig":{"buildInformationVisible":false,"logLevelApp":"info","logLevelMetrics":"info","openTelemetryClientEnabled":false,"openTelemetryConfigName":"f5","openTelemetryServiceVersion":"25.3.0","openTelemetryUniverse":"prod","openTelemetryCollector":"http://localhost:4318","openTelemetryRouteChangeAllowedTime":"5000","apolloDevToolsEnabled":false,"inboxMuteWipFeatureEnabled":false},"isFallback":false,"isExperimentalCompile":false,"dynamicIds":["./components/customComponent/CustomComponent/CustomComponent.tsx","./components/community/Navbar/NavbarWidget.tsx","./components/community/Breadcrumb/BreadcrumbWidget.tsx","./components/tags/TagsHeaderWidget/TagsHeaderWidget.tsx","./components/messages/MessageListForNodeByRecentActivityWidget/MessageListForNodeByRecentActivityWidget.tsx","./components/tags/TagSubscriptionAction/TagSubscriptionAction.tsx","./components/customComponent/CustomComponentContent/TemplateContent.tsx","../shared/client/components/common/List/ListGroup/ListGroup.tsx","./components/messages/MessageView/MessageView.tsx","./components/messages/MessageView/MessageViewInline/MessageViewInline.tsx","../shared/client/components/common/Pager/PagerLoadMore/PagerLoadMore.tsx","./components/customComponent/CustomComponentContent/HtmlContent.tsx","./components/customComponent/CustomComponentContent/CustomComponentScripts.tsx"],"appGip":true,"scriptLoader":[]}