Skip to content

Commit 4965245

Browse files
committed
Add an output package containing artifact representation and functions to create/save the output files
1 parent 3d2cac7 commit 4965245

File tree

1 file changed

+190
-0
lines changed

1 file changed

+190
-0
lines changed

pkg/generate/output/artifact.go

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
14+
package output
15+
16+
import (
17+
"crypto/sha1"
18+
"encoding/hex"
19+
"io"
20+
"io/ioutil"
21+
"os"
22+
"path/filepath"
23+
"time"
24+
25+
"github.com/ghodss/yaml"
26+
27+
"github.com/aws-controllers-k8s/code-generator/pkg/version"
28+
)
29+
30+
const (
31+
outputFileName = "output.yaml"
32+
)
33+
34+
// UpdateReason is the reason a package got modified.
35+
type UpdateReason string
36+
37+
const (
38+
// UpdateReasonAPIGeneration should be used when an API package
39+
// is modified by the APIs generator (ack-generate apis).
40+
UpdateReasonAPIGeneration UpdateReason = "API generation"
41+
42+
// UpdateReasonConversionFunctionsGeneration Should be used when
43+
// an API package is modified by conversion functions generator.
44+
// TODO(hilalymh) ack-generate conversion-functions
45+
UpdateReasonConversionFunctionsGeneration UpdateReason = "Conversion functions generation"
46+
)
47+
48+
// Artifact represent the parameters used the generate/update the
49+
// API version directory.
50+
//
51+
// This type is public because soon it will be used by conversion generators
52+
// to load APIs artifacts.
53+
// TODO(hilalymh) Add functions to load/edit artifact files.
54+
type Artifact struct {
55+
// The APIs version e.g v1alpha2
56+
APIVersion string `json:"apis_version"`
57+
// The checksum of all the combined files generated within the APIs directory
58+
APIDirectoryChecksum string `json:"apis_directory_checksum"`
59+
// Last modification reason
60+
LastModification lastModificationInfo `json:"last_modification"`
61+
// AWS SDK Go version used generate the APIs
62+
AWSSDKGoVersion string `json:"aws_sdk_go_version"`
63+
// Informatiom about the ack-generate binary used to generate the APIs
64+
ACKGenerateInfo ackGenerateInfo `json:"ack_generate_info"`
65+
// Information about the generator config file used to generate the APIs
66+
GeneratorConfigInfo generatorConfigInfo `json:"generator_config_info"`
67+
}
68+
69+
// ack-generate binary information
70+
type ackGenerateInfo struct {
71+
Version string `json:"version"`
72+
GoVersion string `json:"go_version"`
73+
BuildDate string `json:"build_date"`
74+
BuildHash string `json:"build_hash"`
75+
}
76+
77+
// generator.yaml information
78+
type generatorConfigInfo struct {
79+
OriginalFileName string `json:"original_file_name"`
80+
FileChecksum string `json:"file_checksum"`
81+
}
82+
83+
// last modification information
84+
type lastModificationInfo struct {
85+
// UTC Timestamp
86+
Timestamp string `json:"timestamp"`
87+
// Modification reason
88+
Reason UpdateReason `json:"reason"`
89+
}
90+
91+
// CreateArtifact gathers information about the generated code and save
92+
// a yaml version in the API version directory
93+
func CreateArtifact(
94+
apiVersion string,
95+
apisPath string,
96+
modificationReason UpdateReason,
97+
awsSDKGo string,
98+
generatorFileName string,
99+
) error {
100+
filesDirectory := filepath.Join(apisPath, apiVersion)
101+
hash, err := hashDirectoryContent(filesDirectory)
102+
if err != nil {
103+
return err
104+
}
105+
106+
generatorFileHash, err := hashFile(generatorFileName)
107+
if err != nil {
108+
return err
109+
}
110+
111+
artifact := &Artifact{
112+
APIVersion: apiVersion,
113+
APIDirectoryChecksum: hash,
114+
LastModification: lastModificationInfo{
115+
Timestamp: time.Now().UTC().String(),
116+
Reason: modificationReason,
117+
},
118+
AWSSDKGoVersion: awsSDKGo,
119+
ACKGenerateInfo: ackGenerateInfo{
120+
Version: version.Version,
121+
BuildDate: version.BuildDate,
122+
BuildHash: version.BuildHash,
123+
GoVersion: version.GoVersion,
124+
},
125+
GeneratorConfigInfo: generatorConfigInfo{
126+
OriginalFileName: filepath.Base(generatorFileName),
127+
FileChecksum: generatorFileHash,
128+
},
129+
}
130+
131+
data, err := yaml.Marshal(artifact)
132+
if err != nil {
133+
return err
134+
}
135+
136+
err = ioutil.WriteFile(filepath.Join(filesDirectory, outputFileName), data, os.ModePerm)
137+
if err != nil {
138+
return err
139+
}
140+
return nil
141+
}
142+
143+
// hashDirectoryContent returns the sha1 checksum of a given directory. It will walk
144+
// the file tree of a directory and combine and the file contents before hashing it.
145+
func hashDirectoryContent(directory string) (string, error) {
146+
h := sha1.New()
147+
err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
148+
if err != nil {
149+
return err
150+
}
151+
if !info.IsDir() {
152+
// ignore yaml files (output.yaml and generator.yaml)
153+
fileExtension := filepath.Ext(info.Name())
154+
if fileExtension == ".yaml" {
155+
return nil
156+
}
157+
158+
fileReader, err := os.Open(path)
159+
if err != nil {
160+
return err
161+
}
162+
_, err = io.Copy(h, fileReader)
163+
if err != nil {
164+
return err
165+
}
166+
}
167+
return nil
168+
})
169+
if err != nil {
170+
return "", err
171+
}
172+
173+
hash := hex.EncodeToString(h.Sum(nil))
174+
return hash, nil
175+
}
176+
177+
// hashFile returns the sha1 hash of a given file
178+
func hashFile(filename string) (string, error) {
179+
h := sha1.New()
180+
fileReader, err := os.Open(filename)
181+
if err != nil {
182+
return "", err
183+
}
184+
_, err = io.Copy(h, fileReader)
185+
if err != nil {
186+
return "", err
187+
}
188+
hash := hex.EncodeToString(h.Sum(nil))
189+
return hash, nil
190+
}

0 commit comments

Comments
 (0)