Skip to content

Commit e855f8e

Browse files
committed
[FAB-678] Break out Dockerfile generation
We will use this later in the series to extract critical info such as FROM descriptors. Change-Id: I03c74fa22f8fe1e38a941d352807dd641a53850a Signed-off-by: Greg Haskins <[email protected]>
1 parent 2f801c7 commit e855f8e

File tree

4 files changed

+107
-45
lines changed

4 files changed

+107
-45
lines changed

core/chaincode/platforms/car/platform.go

+6-7
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,9 @@ func (carPlatform *Platform) GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byt
4242
return ioutil.ReadFile(spec.ChaincodeID.Path)
4343
}
4444

45-
func (carPlatform *Platform) GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec, tw *tar.Writer) (string, error) {
45+
func (carPlatform *Platform) GenerateDockerfile(cds *pb.ChaincodeDeploymentSpec) (string, error) {
4646

4747
var buf []string
48-
var err error
4948

5049
spec := cds.ChaincodeSpec
5150

@@ -57,10 +56,10 @@ func (carPlatform *Platform) GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec
5756

5857
dockerFileContents := strings.Join(buf, "\n")
5958

60-
err = cutil.WriteBytesToPackage("codepackage.car", cds.CodePackage, tw)
61-
if err != nil {
62-
return "", err
63-
}
64-
6559
return dockerFileContents, nil
6660
}
61+
62+
func (carPlatform *Platform) GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec, tw *tar.Writer) error {
63+
64+
return cutil.WriteBytesToPackage("codepackage.car", cds.CodePackage, tw)
65+
}

core/chaincode/platforms/golang/platform.go

+6-7
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,10 @@ func (goPlatform *Platform) GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte
125125
return payload, nil
126126
}
127127

128-
func (goPlatform *Platform) GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec, tw *tar.Writer) (string, error) {
128+
func (goPlatform *Platform) GenerateDockerfile(cds *pb.ChaincodeDeploymentSpec) (string, error) {
129129

130-
var err error
131130
var buf []string
131+
var err error
132132

133133
spec := cds.ChaincodeSpec
134134

@@ -154,10 +154,9 @@ func (goPlatform *Platform) GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec,
154154

155155
dockerFileContents := strings.Join(buf, "\n")
156156

157-
err = cutil.WriteBytesToPackage("codepackage.tgz", cds.CodePackage, tw)
158-
if err != nil {
159-
return "", err
160-
}
161-
162157
return dockerFileContents, nil
163158
}
159+
160+
func (goPlatform *Platform) GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec, tw *tar.Writer) error {
161+
return cutil.WriteBytesToPackage("codepackage.tgz", cds.CodePackage, tw)
162+
}

core/chaincode/platforms/java/platform.go

+5-7
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ func (javaPlatform *Platform) GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]by
118118
return payload, nil
119119
}
120120

121-
func (javaPlatform *Platform) GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec, tw *tar.Writer) (string, error) {
122-
121+
func (javaPlatform *Platform) GenerateDockerfile(cds *pb.ChaincodeDeploymentSpec) (string, error) {
123122
var err error
124123
var buf []string
125124

@@ -136,10 +135,9 @@ func (javaPlatform *Platform) GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpe
136135

137136
dockerFileContents := strings.Join(buf, "\n")
138137

139-
err = cutil.WriteBytesToPackage("codepackage.tgz", cds.CodePackage, tw)
140-
if err != nil {
141-
return "", err
142-
}
143-
144138
return dockerFileContents, nil
145139
}
140+
141+
func (javaPlatform *Platform) GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec, tw *tar.Writer) error {
142+
return cutil.WriteBytesToPackage("codepackage.tgz", cds.CodePackage, tw)
143+
}

core/chaincode/platforms/platforms.go

+90-24
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import (
2525

2626
"strings"
2727

28+
"io/ioutil"
29+
2830
"github.com/hyperledger/fabric/core/chaincode/platforms/car"
2931
"github.com/hyperledger/fabric/core/chaincode/platforms/golang"
3032
"github.com/hyperledger/fabric/core/chaincode/platforms/java"
@@ -39,7 +41,8 @@ import (
3941
type Platform interface {
4042
ValidateSpec(spec *pb.ChaincodeSpec) error
4143
GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte, error)
42-
GenerateDockerBuild(spec *pb.ChaincodeDeploymentSpec, tw *tar.Writer) (string, error)
44+
GenerateDockerfile(spec *pb.ChaincodeDeploymentSpec) (string, error)
45+
GenerateDockerBuild(spec *pb.ChaincodeDeploymentSpec, tw *tar.Writer) error
4346
}
4447

4548
var logger = logging.MustGetLogger("chaincode-platform")
@@ -69,59 +72,122 @@ func GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte, error) {
6972
return platform.GetDeploymentPayload(spec)
7073
}
7174

72-
func generateDockerBuild(cds *pb.ChaincodeDeploymentSpec, tw *tar.Writer) error {
73-
74-
platform, err := Find(cds.ChaincodeSpec.Type)
75-
if err != nil {
76-
return fmt.Errorf("Failed to determine platform type: %s", err)
75+
func getPeerTLSCert() ([]byte, error) {
76+
path := viper.GetString("peer.tls.cert.file")
77+
if _, err := os.Stat(path); os.IsNotExist(err) {
78+
// It's not an error if the file doesn't exist, we simply do not have a cert
79+
return nil, nil
7780
}
7881

79-
dockerFileBase, err := platform.GenerateDockerBuild(cds, tw)
80-
if err != nil {
81-
return fmt.Errorf("Failed to generate platform-specific docker build: %s", err)
82-
}
82+
// FIXME: FAB-2037 - ensure we sanely resolve relative paths specified in the yaml
83+
return ioutil.ReadFile(path)
84+
}
85+
86+
func generateDockerfile(platform Platform, cds *pb.ChaincodeDeploymentSpec, tls bool) ([]byte, error) {
8387

8488
var buf []string
8589

86-
buf = append(buf, dockerFileBase)
90+
// ----------------------------------------------------------------------------------------------------
91+
// Let the platform define the base Dockerfile
92+
// ----------------------------------------------------------------------------------------------------
93+
base, err := platform.GenerateDockerfile(cds)
94+
if err != nil {
95+
return nil, fmt.Errorf("Failed to generate platform-specific Dockerfile: %s", err)
96+
}
8797

88-
// NOTE: We bake the peer TLS certificate in at the time we build the chaincode container if a cert is
89-
// found, regardless of whether TLS is enabled or not. The main implication is that if the adminstrator
90-
// updates the peer cert, the chaincode containers will need to be invalidated and rebuilt.
91-
// We will manage enabling or disabling TLS at container run time via CORE_PEER_TLS_ENABLED
92-
hostTLSPath := viper.GetString("peer.tls.cert.file")
93-
if _, err = os.Stat(hostTLSPath); err == nil {
98+
buf = append(buf, base)
9499

100+
// ----------------------------------------------------------------------------------------------------
101+
// Then augment it with any general options
102+
// ----------------------------------------------------------------------------------------------------
103+
if tls {
95104
const guestTLSPath = "/etc/hyperledger/fabric/peer.crt"
96105

97106
buf = append(buf, "ENV CORE_PEER_TLS_CERT_FILE="+guestTLSPath)
98107
buf = append(buf, "COPY peer.crt "+guestTLSPath)
108+
}
109+
110+
// ----------------------------------------------------------------------------------------------------
111+
// Finalize it
112+
// ----------------------------------------------------------------------------------------------------
113+
contents := strings.Join(buf, "\n")
114+
115+
return []byte(contents), nil
116+
}
117+
118+
type InputFiles map[string][]byte
119+
120+
func generateDockerBuild(platform Platform, cds *pb.ChaincodeDeploymentSpec, inputFiles InputFiles, tw *tar.Writer) error {
99121

100-
err = cutil.WriteFileToPackage(hostTLSPath, "peer.crt", tw)
122+
var err error
123+
124+
// ----------------------------------------------------------------------------------------------------
125+
// First stream out our static inputFiles
126+
// ----------------------------------------------------------------------------------------------------
127+
for name, data := range inputFiles {
128+
err = cutil.WriteBytesToPackage(name, data, tw)
101129
if err != nil {
102-
return fmt.Errorf("Failed to inject peer certificate: %s", err)
130+
return fmt.Errorf("Failed to inject Dockerfile: %s", err)
103131
}
104132
}
105133

106-
dockerFileContents := strings.Join(buf, "\n")
107-
108-
err = cutil.WriteBytesToPackage("Dockerfile", []byte(dockerFileContents), tw)
134+
// ----------------------------------------------------------------------------------------------------
135+
// Now give the platform an opportunity to contribute its own context to the build
136+
// ----------------------------------------------------------------------------------------------------
137+
err = platform.GenerateDockerBuild(cds, tw)
109138
if err != nil {
110-
return fmt.Errorf("Failed to inject Dockerfile: %s", err)
139+
return fmt.Errorf("Failed to generate platform-specific docker build: %s", err)
111140
}
112141

113142
return nil
114143
}
115144

116145
func GenerateDockerBuild(cds *pb.ChaincodeDeploymentSpec) (io.Reader, error) {
117146

147+
inputFiles := make(InputFiles)
148+
149+
// ----------------------------------------------------------------------------------------------------
150+
// Determine our platform driver from the spec
151+
// ----------------------------------------------------------------------------------------------------
152+
platform, err := Find(cds.ChaincodeSpec.Type)
153+
if err != nil {
154+
return nil, fmt.Errorf("Failed to determine platform type: %s", err)
155+
}
156+
157+
// ----------------------------------------------------------------------------------------------------
158+
// Transfer the peer's TLS certificate to our list of input files, if applicable
159+
// ----------------------------------------------------------------------------------------------------
160+
// NOTE: We bake the peer TLS certificate in at the time we build the chaincode container if a cert is
161+
// found, regardless of whether TLS is enabled or not. The main implication is that if the administrator
162+
// updates the peer cert, the chaincode containers will need to be invalidated and rebuilt.
163+
// We will manage enabling or disabling TLS at container run time via CORE_PEER_TLS_ENABLED
164+
cert, err := getPeerTLSCert()
165+
if err != nil {
166+
return nil, fmt.Errorf("Failed to read the TLS certificate: %s", err)
167+
}
168+
169+
inputFiles["peer.crt"] = cert
170+
171+
// ----------------------------------------------------------------------------------------------------
172+
// Generate the Dockerfile specific to our context
173+
// ----------------------------------------------------------------------------------------------------
174+
dockerFile, err := generateDockerfile(platform, cds, cert != nil)
175+
if err != nil {
176+
return nil, fmt.Errorf("Failed to generate a Dockerfile: %s", err)
177+
}
178+
179+
inputFiles["Dockerfile"] = dockerFile
180+
181+
// ----------------------------------------------------------------------------------------------------
182+
// Finally, launch an asynchronous process to stream all of the above into a docker build context
183+
// ----------------------------------------------------------------------------------------------------
118184
input, output := io.Pipe()
119185

120186
go func() {
121187
gw := gzip.NewWriter(output)
122188
tw := tar.NewWriter(gw)
123189

124-
err := generateDockerBuild(cds, tw)
190+
err := generateDockerBuild(platform, cds, inputFiles, tw)
125191
if err != nil {
126192
logger.Error(err)
127193
}

0 commit comments

Comments
 (0)