Is there a way using an API to globally hide a fixlet?

Is there a way using the Platform API, or the REST API, or some other method to programmatically globally hide fixlets?

I want to globally hide fixlets that are not needed to speed up console performance.

I'd like to be able to automatically hide the following: http://bigfix.me/relevance/details/2999700

names of it whose(0 = open action count of it) of bes fixlets whose(name of it contains " (Superseded)" AND fixlet flag of it AND globally visible flag of it AND not custom flag of it AND (0 = applicable computer count of it))

I don’t think there’s a way with APIs right now to currently do this, but I’ve filed a bug internally to track this issue (65962).

1 Like

You can put an entry in the FIXLETS_VISIBILITY table in the DB for each ID you want to hide. Set IsVisible to 0 and it will be globally hidden.

1 Like

This requires writing to the DB directly, which is not ideal.

I currently have a scenario where we need to update fixlet visibility in bulk.
I couldn’t find a way to do this using rest api. Looks like updating the database (not ideal though) is the only way to achieve this.

I was wondering if this capability has been added of if anyone had any insight into this? We would really like to be able to globally hide/unhide fixlets programmatically if possible.

1 Like

This is still not added. I had raised an HCL idea for same but it was moved to not implement. We are currently doing this in our environment by direct database updates.

1 Like

This is easier said than done, because this table has a sequence number, manyversions, and other values and entries in this table do not exist unless an item has already been hidden.

I went poking around and figured out there is a stored procedure called dbo.update_fixlet_visibility you can call that will handle this for you, if you pass it in the SiteID and FixletID you want to hide.

The problem is, you cannot easily get SiteID and FixletID of content to hide.

This SQL query will get you this by joining 2 tables:

/****** SideID, FixletID of Superseded Fixlets ******/
SELECT 
      SiteNameMapTable.[SiteID]
    , ExternalFixletsTable.[ID] AS [FixletID]
FROM [BFEnterprise].[dbo].[EXTERNAL_OBJECT_DEFS] AS ExternalFixletsTable
INNER JOIN [BFEnterprise].[dbo].[SITENAMEMAP] AS SiteNameMapTable
    ON ExternalFixletsTable.[Sitename] = SiteNameMapTable.[Sitename]
WHERE ExternalFixletsTable.[IsFixlet] = 1
  AND ExternalFixletsTable.[Name] LIKE '% (Superseded)%'

Then this SQL Query will give you the ones that are not already hidden by checking that they do not already have entries in the visibility table:

/****** SiteID, FixletID for External Fixlets that are Superseded but NOT hidden ******/
SELECT 
      SiteNameMapTable.[SiteID]
    , ExternalFixletsTable.[ID] AS [FixletID]
FROM [BFEnterprise].[dbo].[EXTERNAL_OBJECT_DEFS] AS ExternalFixletsTable
INNER JOIN [BFEnterprise].[dbo].[SITENAMEMAP] AS SiteNameMapTable
    ON ExternalFixletsTable.[Sitename] = SiteNameMapTable.[Sitename]
WHERE ExternalFixletsTable.[IsFixlet] = 1
  AND ExternalFixletsTable.[Name] LIKE '% (Superseded)%'
  AND NOT EXISTS (
      SELECT 1 
      FROM [BFEnterprise].[dbo].[FIXLET_VISIBILITY] AS VisibilityTable
      WHERE VisibilityTable.[SiteID] = SiteNameMapTable.[SiteID]
        AND VisibilityTable.[FixletID] = ExternalFixletsTable.[ID]
  )

Then this complicated SQL Cursor will take all of the results from the above query and feed them into the stored procedure that will hide the content for you:

/****** Call Stored Procedure to hide all Superseded Content ******/
DECLARE @CurrentSiteID INT;
DECLARE @CurrentFixletID INT;

-- 1. Declare the cursor using your "missing items" query
DECLARE FixletCursor CURSOR FOR
SELECT 
      SiteNameMapTable.[SiteID]
    , ExternalFixletsTable.[ID]
FROM [BFEnterprise].[dbo].[EXTERNAL_OBJECT_DEFS] AS ExternalFixletsTable
INNER JOIN [BFEnterprise].[dbo].[SITENAMEMAP] AS SiteNameMapTable
    ON ExternalFixletsTable.[Sitename] = SiteNameMapTable.[Sitename]
WHERE ExternalFixletsTable.[IsFixlet] = 1
  AND ExternalFixletsTable.[Name] LIKE '% (Superseded)%'
  AND NOT EXISTS (
      SELECT 1 
      FROM [BFEnterprise].[dbo].[FIXLET_VISIBILITY] AS VisibilityTable
      WHERE VisibilityTable.[SiteID] = SiteNameMapTable.[SiteID]
        AND VisibilityTable.[FixletID] = ExternalFixletsTable.[ID]
  );

-- 2. Open the cursor and begin the loop
OPEN FixletCursor;

FETCH NEXT FROM FixletCursor INTO @CurrentSiteID, @CurrentFixletID;

WHILE @@FETCH_STATUS = 0
BEGIN
    -- 3. Call the Stored Procedure for the current row
    EXEC dbo.update_fixlet_visibility 
        @siteID = @CurrentSiteID, 
        @fixletID = @CurrentFixletID, 
        @isVisible = 0;

    -- Fetch the next row
    FETCH NEXT FROM FixletCursor INTO @CurrentSiteID, @CurrentFixletID;
END

-- 4. Clean up
CLOSE FixletCursor;
DEALLOCATE FixletCursor;

Would I recommend this approach in production? Not really, I’d much rather this only hide content that has no relevant computers that have reported in the last 30 days and no open actions, but that would make this even more complicated to do and this is already quite complicated.

That said, this was an interesting exercise.

6 Likes

You might not be surprised to find that I couldn’t leave this alone and incorporated this logic as well:


DECLARE @CurrentSiteID INT;
DECLARE @CurrentFixletID INT;

-- 1. Declare the cursor using the CTE to safely exclude active items
DECLARE FixletCursor CURSOR FOR
    WITH CombinedFixletsExclude AS (
        -- 1. Exclude if it has at least 1 relevant computer
        SELECT DISTINCT [SiteID]
              ,[ID] As FixletID
        FROM [BFEnterprise].[dbo].[FIXLETRESULTS]
        WHERE [IsRelevant] = 1

        UNION

        -- 2. Exclude if it has at least 1 open action
        SELECT [SourceSiteID] As SiteID
              ,[SourceContentID] As FixletID
        FROM [BFEnterprise].[dbo].[ACTIONS]
        WHERE [SourceSiteID] is not NULL
          AND [IsStopped] = 0
          AND [IsDeleted] = 0

        UNION

        -- 3. Exclude if it already has an entry in the visibility table
        SELECT [SiteID]
              ,[FixletID]
          FROM [BFEnterprise].[dbo].[FIXLET_VISIBILITY]
    )
    SELECT 
          SiteNameMapTable.[SiteID]
        , ExternalFixletsTable.[ID]
    FROM [BFEnterprise].[dbo].[EXTERNAL_OBJECT_DEFS] AS ExternalFixletsTable
    INNER JOIN [BFEnterprise].[dbo].[SITENAMEMAP] AS SiteNameMapTable
        ON ExternalFixletsTable.[Sitename] = SiteNameMapTable.[Sitename]
    WHERE ExternalFixletsTable.[IsFixlet] = 1
      AND ExternalFixletsTable.[Name] LIKE '% (Superseded)%'
      -- The Logic: Only select items that DO NOT exist in your Combined Exclude list
      AND NOT EXISTS (
          SELECT 1 
          FROM CombinedFixletsExclude AS ExcludeList
          WHERE ExcludeList.[SiteID] = SiteNameMapTable.[SiteID]
            AND ExcludeList.[FixletID] = ExternalFixletsTable.[ID]
      );

-- 2. Open the cursor and begin the loop
OPEN FixletCursor;

FETCH NEXT FROM FixletCursor INTO @CurrentSiteID, @CurrentFixletID;

WHILE @@FETCH_STATUS = 0
BEGIN
    -- 3. Call the Stored Procedure for the current row
    -- We assume isVisible = 0 because we want to hide these
    EXEC dbo.update_fixlet_visibility 
        @siteID = @CurrentSiteID, 
        @fixletID = @CurrentFixletID, 
        @isVisible = 0;

    FETCH NEXT FROM FixletCursor INTO @CurrentSiteID, @CurrentFixletID;
END

-- 4. Clean up
CLOSE FixletCursor;
DEALLOCATE FixletCursor;

Obviously this is worth careful consideration especially in production. Not a bad idea to backup the DB first. But theoretically this could be run once a week in production on a schedule using a SQL agent or something.

Also the logic is such that if this hides something, and you decide to unhide it… it should stay unhidden as a result for it will still be in the visibility table.

I know session relevance isn’t easy… but it took me ~30min to write the session relevance to define the set of fixlets I want to hide in 2015. It took me 11 years to write the SQL for the same, lol.

I updated my github with this latest code: tools/SQL/BigFix_FixletsExternal_Superseded_StoredProcedureHide.sql at master · jgstew/tools · GitHub

1 Like