zotregistry.io/zot@v1.4.4-0.20231124084042-02a8ed785457/pkg/common/common.go (about)

     1  package common
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"io/fs"
     9  	"os"
    10  	"regexp"
    11  	"strings"
    12  	"syscall"
    13  	"time"
    14  	"unicode/utf8"
    15  )
    16  
    17  const (
    18  	httpTimeout        = 5 * time.Minute
    19  	certsPath          = "/etc/containers/certs.d"
    20  	homeCertsDir       = ".config/containers/certs.d"
    21  	clientCertFilename = "client.cert"
    22  	clientKeyFilename  = "client.key"
    23  	caCertFilename     = "ca.crt"
    24  
    25  	CosignSignature   = "cosign"
    26  	CosignSigKey      = "dev.cosignproject.cosign/signature"
    27  	NotationSignature = "notation"
    28  	// same value as github.com/notaryproject/notation-go/registry.ArtifactTypeNotation (assert by internal test).
    29  	// reason used: to reduce zot minimal binary size (otherwise adds oras.land/oras-go/v2 deps).
    30  	ArtifactTypeNotation = "application/vnd.cncf.notary.signature"
    31  	ArtifactTypeCosign   = "application/vnd.dev.cosign.artifact.sig.v1+json"
    32  )
    33  
    34  var cosignTagRule = regexp.MustCompile(`sha256\-.+\.sig`)
    35  
    36  func IsCosignTag(tag string) bool {
    37  	return cosignTagRule.MatchString(tag)
    38  }
    39  
    40  func Contains[T comparable](elems []T, v T) bool {
    41  	for _, s := range elems {
    42  		if v == s {
    43  			return true
    44  		}
    45  	}
    46  
    47  	return false
    48  }
    49  
    50  // first match of item in [].
    51  func Index(slice []string, item string) int {
    52  	for k, v := range slice {
    53  		if item == v {
    54  			return k
    55  		}
    56  	}
    57  
    58  	return -1
    59  }
    60  
    61  // remove matches of item in [].
    62  func RemoveFrom(inputSlice []string, item string) []string {
    63  	var newSlice []string
    64  
    65  	for _, v := range inputSlice {
    66  		if item != v {
    67  			newSlice = append(newSlice, v)
    68  		}
    69  	}
    70  
    71  	return newSlice
    72  }
    73  
    74  func TypeOf(v interface{}) string {
    75  	return fmt.Sprintf("%T", v)
    76  }
    77  
    78  func DirExists(d string) bool {
    79  	if !utf8.ValidString(d) {
    80  		return false
    81  	}
    82  
    83  	fileInfo, err := os.Stat(d)
    84  	if err != nil {
    85  		if e, ok := err.(*fs.PathError); ok && errors.Is(e.Err, syscall.ENAMETOOLONG) || //nolint: errorlint
    86  			errors.Is(e.Err, syscall.EINVAL) {
    87  			return false
    88  		}
    89  	}
    90  
    91  	if err != nil && os.IsNotExist(err) {
    92  		return false
    93  	}
    94  
    95  	if !fileInfo.IsDir() {
    96  		return false
    97  	}
    98  
    99  	return true
   100  }
   101  
   102  // Used to filter a json fields by using an intermediate struct.
   103  func MarshalThroughStruct(obj interface{}, throughStruct interface{}) ([]byte, error) {
   104  	toJSON, err := json.Marshal(obj)
   105  	if err != nil {
   106  		return []byte{}, err
   107  	}
   108  
   109  	err = json.Unmarshal(toJSON, throughStruct)
   110  	if err != nil {
   111  		return []byte{}, err
   112  	}
   113  
   114  	toJSON, err = json.Marshal(throughStruct)
   115  	if err != nil {
   116  		return []byte{}, err
   117  	}
   118  
   119  	return toJSON, nil
   120  }
   121  
   122  func ContainsStringIgnoreCase(strSlice []string, str string) bool {
   123  	for _, val := range strSlice {
   124  		if strings.EqualFold(val, str) {
   125  			return true
   126  		}
   127  	}
   128  
   129  	return false
   130  }
   131  
   132  // this function will check if tag is a referrers tag
   133  // (https://github.com/opencontainers/distribution-spec/blob/main/spec.md#referrers-tag-schema).
   134  func IsReferrersTag(tag string) bool {
   135  	referrersTagRule := regexp.MustCompile(`sha256\-[A-Za-z0-9]*$`)
   136  
   137  	return referrersTagRule.MatchString(tag)
   138  }
   139  
   140  func IsContextDone(ctx context.Context) bool {
   141  	select {
   142  	case <-ctx.Done():
   143  		return true
   144  	default:
   145  		return false
   146  	}
   147  }