go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/featureflags.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  //
     5  // In this file we introduce feature flags. They help us activate optional
     6  // features on requests.
     7  //
     8  // Features can only be activated, never deactivated. Features are efficiently encoded.
     9  // They are introduced at a given version and destined to be removed at a later version.
    10  // Please mark them accordingly. Feature flags are short term contextual information.
    11  //
    12  // Example usage:
    13  //
    14  // features := []Feature{ MassResolver, LiveQueries }
    15  //
    16  // features.IsActive( MassResolver )   // true
    17  //
    18  
    19  package cnquery
    20  
    21  //go:generate go run golang.org/x/tools/cmd/stringer -type=Feature
    22  
    23  import (
    24  	"bytes"
    25  	"context"
    26  	"encoding/base64"
    27  )
    28  
    29  const (
    30  	// For all features, use this format:
    31  	// desc:   A description of this feature and what it does...
    32  	// start:  vX.x  (the version when it ix introduced)
    33  	// end:    vZ.0  (the version when this flag will be removed)
    34  
    35  	// Feature flags:
    36  
    37  	// MassQueries feature flag
    38  	// desc:   Resolve similar queries the same way. If 100 assets have the same
    39  	//         dependent queries and overrides, they create the same resolved
    40  	//         plan. Cannot be used with old resolver at the same time for asset.
    41  	// start:  v3.x, available at v4.x, default at v5.x
    42  	// end:    v6.0 => default now, no need to set it anymore
    43  	MassQueries Feature = iota + 1
    44  
    45  	// PiperCode feature flag
    46  	// desc:   Allows MQL to use variable references across blocks. Fully changes
    47  	//         the compiled code.
    48  	// start:  v5.x
    49  	// end:    v7.0 => default now, no need to set it anymore
    50  	PiperCode
    51  
    52  	// BoolAssertions feature flag
    53  	// desc:  Only boolean results are checked when evaluating a query for success
    54  	//
    55  	// start: v6.x
    56  	// end:   v8.0
    57  	BoolAssertions
    58  
    59  	// K8sNodeDiscovery feature flag
    60  	// desc:  Enables discovery of Kubernetes cluster nodes as individual assets
    61  	//
    62  	// start: v6.12
    63  	// end:   unknown
    64  	K8sNodeDiscovery
    65  
    66  	// MQLAssetContext feature flag
    67  	//
    68  	// start: v7.0
    69  	// end:   v8.0
    70  	MQLAssetContext
    71  
    72  	// ErrorsAsFailures feature flag
    73  	// desc:  Errors are treated as failures
    74  	//        See https://www.notion.so/mondoo/Errors-and-Scoring-5dc554348aad4118a1dbf35123368329
    75  	// start: v8.x
    76  	// end:   v9.0
    77  	ErrorsAsFailures
    78  )
    79  
    80  // FeaturesValue is a map from feature name to feature flag
    81  var FeaturesValue = map[string]Feature{
    82  	MassQueries.String():      MassQueries,
    83  	PiperCode.String():        PiperCode,
    84  	BoolAssertions.String():   BoolAssertions,
    85  	MQLAssetContext.String():  MQLAssetContext,
    86  	ErrorsAsFailures.String(): ErrorsAsFailures,
    87  }
    88  
    89  // DefaultFeatures are a set of default flags that are active
    90  var DefaultFeatures = Features{
    91  	byte(MassQueries),
    92  	byte(PiperCode),
    93  }
    94  
    95  // Features is a collection of activated features
    96  type Features []byte
    97  
    98  // Feature is a simple feature flag
    99  type Feature byte
   100  
   101  // IsActive returns true if the given feature has been requested in this list
   102  func (f Features) IsActive(feature Feature) bool {
   103  	return bytes.IndexByte(f, byte(feature)) != -1
   104  }
   105  
   106  // Encode a set of features to base64
   107  func (f Features) Encode() string {
   108  	return base64.StdEncoding.EncodeToString(f)
   109  }
   110  
   111  // DecodeFeatures that were previously encoded
   112  func DecodeFeatures(s string) (Features, error) {
   113  	data, err := base64.StdEncoding.DecodeString(s)
   114  	return Features(data), err
   115  }
   116  
   117  type featureContextID struct{}
   118  
   119  // SetFeatures to a given context
   120  func SetFeatures(ctx context.Context, fts Features) context.Context {
   121  	return context.WithValue(ctx, featureContextID{}, fts)
   122  }
   123  
   124  // GetFeatures from a given context
   125  func GetFeatures(ctx context.Context) Features {
   126  	f, ok := ctx.Value(featureContextID{}).(Features)
   127  	if !ok {
   128  		// nothing stored, assume empty features
   129  		return Features{}
   130  	}
   131  	return f
   132  }