github.com/bndr/gojenkins@v1.1.0/artifact.go (about) 1 // Copyright 2015 Vadim Kravcenko 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. You may obtain 5 // a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 package gojenkins 16 17 import ( 18 "context" 19 "crypto/md5" 20 "errors" 21 "fmt" 22 "io" 23 "io/ioutil" 24 "os" 25 "path" 26 ) 27 28 // Represents an Artifact 29 type Artifact struct { 30 Jenkins *Jenkins 31 Build *Build 32 FileName string 33 Path string 34 } 35 36 // Get raw byte data of Artifact 37 func (a Artifact) GetData(ctx context.Context) ([]byte, error) { 38 var data string 39 response, err := a.Jenkins.Requester.Get(ctx, a.Path, &data, nil) 40 41 if err != nil { 42 return nil, err 43 } 44 45 code := response.StatusCode 46 if code != 200 { 47 Error.Printf("Jenkins responded with StatusCode: %d", code) 48 return nil, errors.New("Could not get File Contents") 49 } 50 return []byte(data), nil 51 } 52 53 // Save artifact to a specific path, using your own filename. 54 func (a Artifact) Save(ctx context.Context, path string) (bool, error) { 55 data, err := a.GetData(ctx) 56 57 if err != nil { 58 return false, errors.New("No data received, not saving file") 59 } 60 61 if _, err = os.Stat(path); err == nil { 62 Warning.Println("Local Copy already exists, Overwriting...") 63 } 64 65 err = ioutil.WriteFile(path, data, 0644) 66 a.validateDownload(ctx, path) 67 68 if err != nil { 69 return false, err 70 } 71 return true, nil 72 } 73 74 // Save Artifact to directory using Artifact filename. 75 func (a Artifact) SaveToDir(ctx context.Context, dir string) (bool, error) { 76 if _, err := os.Stat(dir); err != nil { 77 Error.Printf("can't save artifact: directory %s does not exist", dir) 78 return false, fmt.Errorf("can't save artifact: directory %s does not exist", dir) 79 } 80 saved, err := a.Save(ctx, path.Join(dir, a.FileName)) 81 if err != nil { 82 return saved, nil 83 } 84 return saved, nil 85 } 86 87 // Compare Remote and local MD5 88 func (a Artifact) validateDownload(ctx context.Context, path string) (bool, error) { 89 localHash := a.getMD5local(path) 90 91 fp := FingerPrint{Jenkins: a.Jenkins, Base: "/fingerprint/", Id: localHash, Raw: new(FingerPrintResponse)} 92 93 valid, err := fp.ValidateForBuild(ctx, a.FileName, a.Build) 94 95 if err != nil { 96 return false, err 97 } 98 if !valid { 99 return false, errors.New("FingerPrint of the downloaded artifact could not be verified") 100 } 101 return true, nil 102 } 103 104 // Get Local MD5 105 func (a Artifact) getMD5local(path string) string { 106 h := md5.New() 107 localFile, err := os.Open(path) 108 if err != nil { 109 return "" 110 } 111 buffer := make([]byte, 1<<20) 112 n, err := localFile.Read(buffer) 113 defer localFile.Close() 114 for err == nil { 115 io.WriteString(h, string(buffer[0:n])) 116 n, err = localFile.Read(buffer) 117 } 118 return fmt.Sprintf("%x", h.Sum(nil)) 119 }