@@ -25,6 +25,8 @@ import (
25
25
26
26
"strings"
27
27
28
+ "io/ioutil"
29
+
28
30
"github.com/hyperledger/fabric/core/chaincode/platforms/car"
29
31
"github.com/hyperledger/fabric/core/chaincode/platforms/golang"
30
32
"github.com/hyperledger/fabric/core/chaincode/platforms/java"
@@ -39,7 +41,8 @@ import (
39
41
type Platform interface {
40
42
ValidateSpec (spec * pb.ChaincodeSpec ) error
41
43
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
43
46
}
44
47
45
48
var logger = logging .MustGetLogger ("chaincode-platform" )
@@ -69,59 +72,122 @@ func GetDeploymentPayload(spec *pb.ChaincodeSpec) ([]byte, error) {
69
72
return platform .GetDeploymentPayload (spec )
70
73
}
71
74
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
77
80
}
78
81
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 ) {
83
87
84
88
var buf []string
85
89
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
+ }
87
97
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 )
94
99
100
+ // ----------------------------------------------------------------------------------------------------
101
+ // Then augment it with any general options
102
+ // ----------------------------------------------------------------------------------------------------
103
+ if tls {
95
104
const guestTLSPath = "/etc/hyperledger/fabric/peer.crt"
96
105
97
106
buf = append (buf , "ENV CORE_PEER_TLS_CERT_FILE=" + guestTLSPath )
98
107
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 {
99
121
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 )
101
129
if err != nil {
102
- return fmt .Errorf ("Failed to inject peer certificate : %s" , err )
130
+ return fmt .Errorf ("Failed to inject Dockerfile : %s" , err )
103
131
}
104
132
}
105
133
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 )
109
138
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 )
111
140
}
112
141
113
142
return nil
114
143
}
115
144
116
145
func GenerateDockerBuild (cds * pb.ChaincodeDeploymentSpec ) (io.Reader , error ) {
117
146
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
+ // ----------------------------------------------------------------------------------------------------
118
184
input , output := io .Pipe ()
119
185
120
186
go func () {
121
187
gw := gzip .NewWriter (output )
122
188
tw := tar .NewWriter (gw )
123
189
124
- err := generateDockerBuild (cds , tw )
190
+ err := generateDockerBuild (platform , cds , inputFiles , tw )
125
191
if err != nil {
126
192
logger .Error (err )
127
193
}
0 commit comments