github.com/cloudfoundry-attic/ltc@v0.0.0-20151123212628-098adc7919fc/docker_runner/docker_metadata_fetcher/docker_metadata_fetcher.go (about)

     1  package docker_metadata_fetcher
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strings"
     7  
     8  	"github.com/cloudfoundry-incubator/ltc/docker_runner/docker_repository_name_formatter"
     9  	"github.com/docker/docker/image"
    10  	"github.com/docker/docker/pkg/nat"
    11  )
    12  
    13  type ImageMetadata struct {
    14  	User         string
    15  	WorkingDir   string
    16  	ExposedPorts []uint16
    17  	StartCommand []string
    18  	Env          []string
    19  }
    20  
    21  //go:generate counterfeiter -o fake_docker_metadata_fetcher/fake_docker_metadata_fetcher.go . DockerMetadataFetcher
    22  type DockerMetadataFetcher interface {
    23  	FetchMetadata(dockerPath string) (*ImageMetadata, error)
    24  }
    25  
    26  type dockerMetadataFetcher struct {
    27  	dockerSessionFactory DockerSessionFactory
    28  }
    29  
    30  func New(sessionFactory DockerSessionFactory) DockerMetadataFetcher {
    31  	return &dockerMetadataFetcher{
    32  		dockerSessionFactory: sessionFactory,
    33  	}
    34  }
    35  
    36  func (fetcher *dockerMetadataFetcher) FetchMetadata(dockerPath string) (*ImageMetadata, error) {
    37  	indexName, remoteName, tag, err := docker_repository_name_formatter.ParseRepoNameAndTagFromImageReference(dockerPath)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  
    42  	var reposName string
    43  	if len(indexName) > 0 {
    44  		reposName = fmt.Sprintf("%s/%s", indexName, remoteName)
    45  	} else {
    46  		reposName = remoteName
    47  	}
    48  
    49  	var session DockerSession
    50  	if session, err = fetcher.dockerSessionFactory.MakeSession(reposName, false); err != nil {
    51  		if !strings.Contains(err.Error(), "this private registry supports only HTTP or HTTPS with an unknown CA certificate") {
    52  			return nil, err
    53  		}
    54  
    55  		session, err = fetcher.dockerSessionFactory.MakeSession(reposName, true)
    56  		if err != nil {
    57  			return nil, err
    58  		}
    59  	}
    60  
    61  	repoData, err := session.GetRepositoryData(remoteName)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	tagsList, err := session.GetRemoteTags(repoData.Endpoints, remoteName)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	imgID, ok := tagsList[tag]
    72  	if !ok {
    73  		return nil, fmt.Errorf("Unknown tag: %s:%s", remoteName, tag)
    74  	}
    75  
    76  	var img *image.Image
    77  	endpoint := repoData.Endpoints[0]
    78  	imgJSON, _, err := session.GetRemoteImageJSON(imgID, endpoint)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	img, err = image.NewImgJSON(imgJSON)
    84  	if err != nil {
    85  		return nil, fmt.Errorf("Error parsing remote image json for specified docker image:\n%s", err)
    86  	}
    87  	if img.Config == nil {
    88  		return nil, fmt.Errorf("Parsing start command failed")
    89  	}
    90  
    91  	startCommand := append(img.Config.Entrypoint.Slice(), img.Config.Cmd.Slice()...)
    92  	exposedPorts := sortPorts(img.ContainerConfig.ExposedPorts)
    93  
    94  	return &ImageMetadata{
    95  		WorkingDir:   img.Config.WorkingDir,
    96  		User:         img.Config.User,
    97  		StartCommand: startCommand,
    98  		ExposedPorts: exposedPorts,
    99  		Env:          img.Config.Env,
   100  	}, nil
   101  }
   102  
   103  func sortPorts(dockerExposedPorts map[nat.Port]struct{}) []uint16 {
   104  	intPorts := make([]int, 0)
   105  	for natPort, _ := range dockerExposedPorts {
   106  		if natPort.Proto() == "tcp" {
   107  			intPorts = append(intPorts, natPort.Int())
   108  		}
   109  	}
   110  	sort.IntSlice(intPorts).Sort()
   111  
   112  	exposedPorts := make([]uint16, 0)
   113  	for _, port := range intPorts {
   114  		exposedPorts = append(exposedPorts, uint16(port))
   115  	}
   116  	return exposedPorts
   117  }