github.com/docker/app@v0.9.1-beta3.0.20210611140623-a48f773ab002/internal/packager/custom.go (about)

     1  package packager
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/deislabs/cnab-go/bundle"
     9  	"github.com/docker/app/internal"
    10  )
    11  
    12  const (
    13  	// DockerAppCustomVersion1_0_0 is the custom payload version 1.0.0
    14  	DockerAppPayloadVersion1_0_0 = "1.0.0"
    15  
    16  	// DockerAppCustomVersionCurrent the current payload version
    17  	// The version must be bumped each time the Payload format change.
    18  	DockerAppPayloadVersionCurrent = DockerAppPayloadVersion1_0_0
    19  )
    20  
    21  // DockerAppCustom contains extension custom data that docker app injects
    22  // in the bundle.
    23  type DockerAppCustom struct {
    24  	// Payload format version
    25  	Version string `json:"version,omitempty"`
    26  	// Custom payload format depends on version
    27  	Payload json.RawMessage `json:"payload,omitempty"`
    28  }
    29  
    30  // CustomPayloadAppVersion is a custom payload with a docker app version
    31  type CustomPayloadAppVersion interface {
    32  	AppVersion() string
    33  }
    34  
    35  type payloadV1_0 struct {
    36  	Version string `json:"app-version"`
    37  }
    38  
    39  func (p payloadV1_0) AppVersion() string {
    40  	return p.Version
    41  }
    42  
    43  func newCustomPayload() (json.RawMessage, error) {
    44  	p := payloadV1_0{Version: internal.Version}
    45  	j, err := json.Marshal(&p)
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  	return j, nil
    50  }
    51  
    52  // CheckAppVersion prints a warning if the bundle was built with a different version of docker app
    53  func CheckAppVersion(stderr io.Writer, bndl *bundle.Bundle) error {
    54  	payload, err := CustomPayload(bndl)
    55  	if err != nil {
    56  		return err
    57  	}
    58  	if payload == nil {
    59  		return nil
    60  	}
    61  
    62  	var version string
    63  	if versionPayload, ok := payload.(CustomPayloadAppVersion); ok {
    64  		version = versionPayload.AppVersion()
    65  	}
    66  	if version != internal.Version {
    67  		fmt.Fprintf(stderr, "WARNING: App Image has been built with a different version of docker app: %q\n", version)
    68  	}
    69  	return nil
    70  }
    71  
    72  // CustomPayload parses and returns the bundle's custom payload
    73  func CustomPayload(b *bundle.Bundle) (interface{}, error) {
    74  	custom, err := parseCustomPayload(b)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	switch version := custom.Version; version {
    80  	case DockerAppPayloadVersion1_0_0:
    81  		var payload payloadV1_0
    82  		if err := json.Unmarshal(custom.Payload, &payload); err != nil {
    83  			return nil, err
    84  		}
    85  		return payload, nil
    86  	default:
    87  		return nil, nil
    88  	}
    89  }
    90  
    91  func parseCustomPayload(b *bundle.Bundle) (DockerAppCustom, error) {
    92  	customMap, ok := b.Custom[internal.CustomDockerAppName]
    93  	if !ok {
    94  		return DockerAppCustom{}, nil
    95  	}
    96  
    97  	customJSON, err := json.Marshal(customMap)
    98  	if err != nil {
    99  		return DockerAppCustom{}, err
   100  	}
   101  
   102  	var custom DockerAppCustom
   103  	if err = json.Unmarshal(customJSON, &custom); err != nil {
   104  		return DockerAppCustom{}, err
   105  	}
   106  
   107  	return custom, nil
   108  }