github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/api/common.go (about)

     1  package api
     2  
     3  import (
     4  	"fmt"
     5  	"mime"
     6  	"path/filepath"
     7  	"sort"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/Sirupsen/logrus"
    12  	"github.com/docker/docker/pkg/system"
    13  	"github.com/docker/docker/pkg/version"
    14  	"github.com/docker/engine-api/types"
    15  	"github.com/docker/libtrust"
    16  )
    17  
    18  // Common constants for daemon and client.
    19  const (
    20  	// Version of Current REST API
    21  	DefaultVersion version.Version = "1.24"
    22  
    23  	// MinVersion represents Minimum REST API version supported
    24  	MinVersion version.Version = "1.12"
    25  
    26  	// NoBaseImageSpecifier is the symbol used by the FROM
    27  	// command to specify that no base image is to be used.
    28  	NoBaseImageSpecifier string = "scratch"
    29  )
    30  
    31  // byPortInfo is a temporary type used to sort types.Port by its fields
    32  type byPortInfo []types.Port
    33  
    34  func (r byPortInfo) Len() int      { return len(r) }
    35  func (r byPortInfo) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
    36  func (r byPortInfo) Less(i, j int) bool {
    37  	if r[i].PrivatePort != r[j].PrivatePort {
    38  		return r[i].PrivatePort < r[j].PrivatePort
    39  	}
    40  
    41  	if r[i].IP != r[j].IP {
    42  		return r[i].IP < r[j].IP
    43  	}
    44  
    45  	if r[i].PublicPort != r[j].PublicPort {
    46  		return r[i].PublicPort < r[j].PublicPort
    47  	}
    48  
    49  	return r[i].Type < r[j].Type
    50  }
    51  
    52  // DisplayablePorts returns formatted string representing open ports of container
    53  // e.g. "0.0.0.0:80->9090/tcp, 9988/tcp"
    54  // it's used by command 'docker ps'
    55  func DisplayablePorts(ports []types.Port) string {
    56  	type portGroup struct {
    57  		first int
    58  		last  int
    59  	}
    60  	groupMap := make(map[string]*portGroup)
    61  	var result []string
    62  	var hostMappings []string
    63  	var groupMapKeys []string
    64  	sort.Sort(byPortInfo(ports))
    65  	for _, port := range ports {
    66  		current := port.PrivatePort
    67  		portKey := port.Type
    68  		if port.IP != "" {
    69  			if port.PublicPort != current {
    70  				hostMappings = append(hostMappings, fmt.Sprintf("%s:%d->%d/%s", port.IP, port.PublicPort, port.PrivatePort, port.Type))
    71  				continue
    72  			}
    73  			portKey = fmt.Sprintf("%s/%s", port.IP, port.Type)
    74  		}
    75  		group := groupMap[portKey]
    76  
    77  		if group == nil {
    78  			groupMap[portKey] = &portGroup{first: current, last: current}
    79  			// record order that groupMap keys are created
    80  			groupMapKeys = append(groupMapKeys, portKey)
    81  			continue
    82  		}
    83  		if current == (group.last + 1) {
    84  			group.last = current
    85  			continue
    86  		}
    87  
    88  		result = append(result, formGroup(portKey, group.first, group.last))
    89  		groupMap[portKey] = &portGroup{first: current, last: current}
    90  	}
    91  	for _, portKey := range groupMapKeys {
    92  		g := groupMap[portKey]
    93  		result = append(result, formGroup(portKey, g.first, g.last))
    94  	}
    95  	result = append(result, hostMappings...)
    96  	return strings.Join(result, ", ")
    97  }
    98  
    99  func formGroup(key string, start, last int) string {
   100  	parts := strings.Split(key, "/")
   101  	groupType := parts[0]
   102  	var ip string
   103  	if len(parts) > 1 {
   104  		ip = parts[0]
   105  		groupType = parts[1]
   106  	}
   107  	group := strconv.Itoa(start)
   108  	if start != last {
   109  		group = fmt.Sprintf("%s-%d", group, last)
   110  	}
   111  	if ip != "" {
   112  		group = fmt.Sprintf("%s:%s->%s", ip, group, group)
   113  	}
   114  	return fmt.Sprintf("%s/%s", group, groupType)
   115  }
   116  
   117  // MatchesContentType validates the content type against the expected one
   118  func MatchesContentType(contentType, expectedType string) bool {
   119  	mimetype, _, err := mime.ParseMediaType(contentType)
   120  	if err != nil {
   121  		logrus.Errorf("Error parsing media type: %s error: %v", contentType, err)
   122  	}
   123  	return err == nil && mimetype == expectedType
   124  }
   125  
   126  // LoadOrCreateTrustKey attempts to load the libtrust key at the given path,
   127  // otherwise generates a new one
   128  func LoadOrCreateTrustKey(trustKeyPath string) (libtrust.PrivateKey, error) {
   129  	err := system.MkdirAll(filepath.Dir(trustKeyPath), 0700)
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  	trustKey, err := libtrust.LoadKeyFile(trustKeyPath)
   134  	if err == libtrust.ErrKeyFileDoesNotExist {
   135  		trustKey, err = libtrust.GenerateECP256PrivateKey()
   136  		if err != nil {
   137  			return nil, fmt.Errorf("Error generating key: %s", err)
   138  		}
   139  		if err := libtrust.SaveKey(trustKeyPath, trustKey); err != nil {
   140  			return nil, fmt.Errorf("Error saving key file: %s", err)
   141  		}
   142  	} else if err != nil {
   143  		return nil, fmt.Errorf("Error loading key file %s: %s", trustKeyPath, err)
   144  	}
   145  	return trustKey, nil
   146  }