Skip to content

Commit aa85178

Browse files
rlfnbRalf
authored andcommitted
initial
1 parent da6130e commit aa85178

File tree

13 files changed

+1013
-1
lines changed

13 files changed

+1013
-1
lines changed

Makefile

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ dist: dist-clean dist/$(MARCH)
281281

282282
.PHONY: dist-all
283283
dist-all: dist-clean $(RELEASE_PLATFORMS:%=dist/%)
284-
dist/%: release/% ccaasbuilder
284+
dist/%: release/% externalbuilder ccaasbuilder
285285
mkdir -p release/$(@F)/config
286286
cp -r sampleconfig/*.yaml release/$(@F)/config
287287
cd release/$(@F) && tar -czvf hyperledger-fabric-$(@F).$(PROJECT_VERSION).tar.gz *
@@ -351,6 +351,11 @@ ccaasbuilder-clean/%:
351351
$(eval platform = $(patsubst ccaasbuilder/%,%,$@) )
352352
cd ccaas_builder && rm -rf $(strip $(platform))
353353

354+
.PHONY: externalbuilder-clean
355+
externalbuilder-clean/%:
356+
$(eval platform = $(patsubst externalbuilder/%,%,$@) )
357+
cd external_builder && rm -rf $(strip $(platform))
358+
354359
.PHONY: ccaasbuilder
355360
ccaasbuilder/%: ccaasbuilder-clean
356361
$(eval platform = $(patsubst ccaasbuilder/%,%,$@) )
@@ -361,8 +366,20 @@ ccaasbuilder/%: ccaasbuilder-clean
361366
cd ccaas_builder && go test -v ./cmd/build && GOOS=$(GOOS) GOARCH=$(GOARCH) go build -buildvcs=false -o ../release/$(strip $(platform))/builders/ccaas/bin/ ./cmd/build/
362367
cd ccaas_builder && go test -v ./cmd/release && GOOS=$(GOOS) GOARCH=$(GOARCH) go build -buildvcs=false -o ../release/$(strip $(platform))/builders/ccaas/bin/ ./cmd/release/
363368

369+
.PHONY: externalbuilder
370+
externalbuilder/%: externalbuilder-clean
371+
$(eval platform = $(patsubst externalbuilder/%,%,$@) )
372+
$(eval GOOS = $(word 1,$(subst -, ,$(platform))))
373+
$(eval GOARCH = $(word 2,$(subst -, ,$(platform))))
374+
@mkdir -p release/$(strip $(platform))/builders/external/bin
375+
cd external_builder && go test -v ./cmd/detect && GOOS=$(GOOS) GOARCH=$(GOARCH) go build -buildvcs=false -o ../release/$(strip $(platform))/builders/external/bin/ ./cmd/detect/
376+
cd external_builder && go test -v ./cmd/build && GOOS=$(GOOS) GOARCH=$(GOARCH) go build -buildvcs=false -o ../release/$(strip $(platform))/builders/external/bin/ ./cmd/build/
377+
cd external_builder && go test -v ./cmd/release && GOOS=$(GOOS) GOARCH=$(GOARCH) go build -buildvcs=false -o ../release/$(strip $(platform))/builders/external/bin/ ./cmd/release/
378+
364379
ccaasbuilder: ccaasbuilder/$(MARCH)
365380

381+
externalbuilder: externalbuilder/$(MARCH)
382+
366383
.PHONY: scan
367384
scan: scan-govulncheck
368385

external_builder/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#SPDX-License-Identifier: Apache-2.0
2+
bin/*

external_builder/cmd/build/main.go

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package main
8+
9+
import (
10+
"bytes"
11+
"encoding/json"
12+
"fmt"
13+
"log"
14+
"os"
15+
"path/filepath"
16+
"strings"
17+
"text/template"
18+
19+
"github.com/otiai10/copy"
20+
"github.com/pkg/errors"
21+
)
22+
23+
var logger = log.New(os.Stderr, "", 0)
24+
25+
type chaincodeMetadata struct {
26+
Type string `json:"type"`
27+
}
28+
29+
// Connection structure is used to represent the
30+
// connection.json file that is supplied in the
31+
// chaincode package.
32+
type connection struct {
33+
Address string `json:"address"`
34+
DialTimeout string `json:"dial_timeout"`
35+
TLS bool `json:"tls_required"`
36+
ClientAuth bool `json:"client_auth_required"`
37+
RootCert string `json:"root_cert"`
38+
ClientKey string `json:"client_key"`
39+
ClientCert string `json:"client_cert"`
40+
}
41+
42+
type Config struct {
43+
PeerName string
44+
}
45+
46+
func main() {
47+
logger.Println("::Build")
48+
49+
if err := run(); err != nil {
50+
logger.Printf("::Error: %v\n", err)
51+
os.Exit(1)
52+
}
53+
54+
logger.Printf("::Build phase completed")
55+
56+
}
57+
58+
func run() error {
59+
if len(os.Args) < 4 {
60+
return fmt.Errorf("incorrect number of arguments")
61+
}
62+
63+
sourceDir, metadataDir, outputDir := os.Args[1], os.Args[2], os.Args[3]
64+
65+
connectionSrcFile := filepath.Join(sourceDir, "/connection.json")
66+
metadataFile := filepath.Clean(filepath.Join(metadataDir, "metadata.json"))
67+
connectionDestFile := filepath.Join(outputDir, "/connection.json")
68+
metainfoSrcDir := filepath.Join(sourceDir, "META-INF")
69+
metainfoDestDir := filepath.Join(outputDir, "META-INF")
70+
71+
// Process and check the metadata file, then copy to the output location
72+
if _, err := os.Stat(metadataFile); err != nil {
73+
return errors.WithMessagef(err, "%s not found ", metadataFile)
74+
}
75+
76+
metadataFileContents, cause := os.ReadFile(metadataFile)
77+
if cause != nil {
78+
return errors.WithMessagef(cause, "%s file not readable", metadataFile)
79+
}
80+
81+
var metadata chaincodeMetadata
82+
if err := json.Unmarshal(metadataFileContents, &metadata); err != nil {
83+
return errors.WithMessage(err, "Unable to parse JSON")
84+
}
85+
86+
if strings.ToLower(metadata.Type) != "external" {
87+
return fmt.Errorf("chaincode type should be external, it is %s", metadata.Type)
88+
}
89+
90+
if err := copy.Copy(metadataDir, outputDir); err != nil {
91+
return fmt.Errorf("failed to copy build metadata folder: %s", err)
92+
}
93+
94+
if _, err := os.Stat(metainfoSrcDir); !os.IsNotExist(err) {
95+
if err := copy.Copy(metainfoSrcDir, metainfoDestDir); err != nil {
96+
return fmt.Errorf("failed to copy build META-INF folder: %s", err)
97+
}
98+
}
99+
100+
// Process and update the connections file
101+
fileInfo, err := os.Stat(connectionSrcFile)
102+
if err != nil {
103+
return errors.WithMessagef(err, "%s not found ", connectionSrcFile)
104+
}
105+
106+
connectionFileContents, err := os.ReadFile(connectionSrcFile)
107+
if err != nil {
108+
return err
109+
}
110+
111+
// read the connection.json file into structure to process
112+
var connectionData connection
113+
if err := json.Unmarshal(connectionFileContents, &connectionData); err != nil {
114+
return err
115+
}
116+
117+
// Treat each of the string fields in the connection.json as Go template
118+
// strings. They can be fixed strings, but if they are templates
119+
// then the JSON string that is defined in CHAINCODE_AS_A_SERVICE_BUILDER_CONFIG
120+
// is used as the 'context' to parse the string
121+
122+
updatedConnection := connection{}
123+
var cfg map[string]interface{}
124+
125+
cfgString := os.Getenv("CHAINCODE_AS_A_SERVICE_BUILDER_CONFIG")
126+
if cfgString != "" {
127+
if err := json.Unmarshal([]byte(cfgString), &cfg); err != nil {
128+
return fmt.Errorf("Failed to unmarshal %s", err)
129+
}
130+
}
131+
132+
updatedConnection.Address, err = execTempl(cfg, connectionData.Address)
133+
if err != nil {
134+
return fmt.Errorf("Failed to parse the Address field template: %s", err)
135+
}
136+
137+
updatedConnection.DialTimeout, err = execTempl(cfg, connectionData.DialTimeout)
138+
if err != nil {
139+
return fmt.Errorf("Failed to parse the DialTimeout field template: %s", err)
140+
}
141+
142+
// if connection is TLS Enabled, updated with the correct information
143+
// no other information is needed for the no-TLS case, so the default can be assumed
144+
// to be good
145+
if connectionData.TLS {
146+
updatedConnection.TLS = true
147+
updatedConnection.ClientAuth = connectionData.ClientAuth
148+
149+
updatedConnection.RootCert, err = execTempl(cfg, connectionData.RootCert)
150+
if err != nil {
151+
return fmt.Errorf("Failed to parse the RootCert field template: %s", err)
152+
}
153+
updatedConnection.ClientKey, err = execTempl(cfg, connectionData.ClientKey)
154+
if err != nil {
155+
return fmt.Errorf("Failed to parse the ClientKey field template: %s", err)
156+
}
157+
updatedConnection.ClientCert, err = execTempl(cfg, connectionData.ClientCert)
158+
if err != nil {
159+
return fmt.Errorf("Failed to parse the ClientCert field template: %s", err)
160+
}
161+
}
162+
163+
updatedConnectionBytes, err := json.Marshal(updatedConnection)
164+
if err != nil {
165+
return fmt.Errorf("failed to marshal updated connection.json file: %s", err)
166+
}
167+
168+
err = os.WriteFile(connectionDestFile, updatedConnectionBytes, fileInfo.Mode())
169+
if err != nil {
170+
return err
171+
}
172+
173+
return nil
174+
175+
}
176+
177+
// execTempl is a helper function to process a template against a string, and return a string
178+
func execTempl(cfg map[string]interface{}, inputStr string) (string, error) {
179+
180+
t, err := template.New("").Option("missingkey=error").Parse(inputStr)
181+
if err != nil {
182+
fmt.Printf("Failed to parse the template: %s", err)
183+
return "", err
184+
}
185+
186+
buf := &bytes.Buffer{}
187+
err = t.Execute(buf, cfg)
188+
if err != nil {
189+
return "", err
190+
}
191+
192+
return buf.String(), nil
193+
}

0 commit comments

Comments
 (0)