8 "git.curoverse.com/arvados.git/sdk/go/arvadosclient"
9 "git.curoverse.com/arvados.git/sdk/go/keepclient"
27 flags := flag.NewFlagSet("keep-block-check", flag.ExitOnError)
29 configFile := flags.String(
32 "Configuration filename. May be either a pathname to a config file, or (for example) 'foo' as shorthand for $HOME/.config/arvados/foo.conf file. This file is expected to specify the values for ARVADOS_API_TOKEN, ARVADOS_API_HOST, ARVADOS_API_HOST_INSECURE, and ARVADOS_BLOB_SIGNING_KEY for the source.")
34 keepServicesJSON := flags.String(
37 "An optional list of available keepservices. "+
38 "If not provided, this list is obtained from api server configured in config-file.")
40 locatorFile := flags.String(
43 "Filename containing the block hashes to be checked. This is required. "+
44 "This file contains the block hashes one per line.")
46 prefix := flags.String(
49 "Block hash prefix. When a prefix is specified, only hashes listed in the file with this prefix will be checked.")
51 // Parse args; omit the first arg which is the command name
52 flags.Parse(os.Args[1:])
54 config, blobSigningKey, err := loadConfig(*configFile)
56 return fmt.Errorf("Error loading configuration from file: %s", err.Error())
59 // get list of block locators to be checked
60 blockLocators, err := getBlockLocators(*locatorFile)
62 return fmt.Errorf("Error reading block hashes to be checked from file: %s", err.Error())
66 kc, err := setupKeepClient(config, *keepServicesJSON)
68 return fmt.Errorf("Error configuring keepclient: %s", err.Error())
71 performKeepBlockCheck(kc, blobSigningKey, *prefix, blockLocators)
75 type apiConfig struct {
82 // Load config from given file
83 func loadConfig(configFile string) (config apiConfig, blobSigningKey string, err error) {
85 err = errors.New("API config file not specified")
89 config, blobSigningKey, err = readConfigFromFile(configFile)
93 var matchTrue = regexp.MustCompile("^(?i:1|yes|true)$")
95 // Read config from file
96 func readConfigFromFile(filename string) (config apiConfig, blobSigningKey string, err error) {
97 if !strings.Contains(filename, "/") {
98 filename = os.Getenv("HOME") + "/.config/arvados/" + filename + ".conf"
101 content, err := ioutil.ReadFile(filename)
107 lines := strings.Split(string(content), "\n")
108 for _, line := range lines {
113 kv := strings.SplitN(line, "=", 2)
114 key := strings.TrimSpace(kv[0])
115 value := strings.TrimSpace(kv[1])
118 case "ARVADOS_API_TOKEN":
119 config.APIToken = value
120 case "ARVADOS_API_HOST":
121 config.APIHost = value
122 case "ARVADOS_API_HOST_INSECURE":
123 config.APIHostInsecure = matchTrue.MatchString(value)
124 case "ARVADOS_EXTERNAL_CLIENT":
125 config.ExternalClient = matchTrue.MatchString(value)
126 case "ARVADOS_BLOB_SIGNING_KEY":
127 blobSigningKey = value
134 // setup keepclient using the config provided
135 func setupKeepClient(config apiConfig, keepServicesJSON string) (kc *keepclient.KeepClient, err error) {
136 arv := arvadosclient.ArvadosClient{
137 ApiToken: config.APIToken,
138 ApiServer: config.APIHost,
139 ApiInsecure: config.APIHostInsecure,
140 Client: &http.Client{Transport: &http.Transport{
141 TLSClientConfig: &tls.Config{InsecureSkipVerify: config.APIHostInsecure}}},
142 External: config.ExternalClient,
145 // if keepServicesJSON is provided, use it to load services; else, use DiscoverKeepServers
146 if keepServicesJSON == "" {
147 kc, err = keepclient.MakeKeepClient(&arv)
152 kc = keepclient.New(&arv)
153 err = kc.LoadKeepServicesFromJSON(keepServicesJSON)
162 // Get list of block locators from the given file
163 func getBlockLocators(locatorFile string) (locators []string, err error) {
164 if locatorFile == "" {
165 err = errors.New("block-hash-file not specified")
169 content, err := ioutil.ReadFile(locatorFile)
175 lines := strings.Split(string(content), "\n")
176 for _, line := range lines {
180 locators = append(locators, strings.TrimSpace(line))
186 // Get block headers from keep. Log any errors.
187 func performKeepBlockCheck(kc *keepclient.KeepClient, blobSigningKey, prefix string, blockLocators []string) {
188 for _, locator := range blockLocators {
189 if !strings.HasPrefix(locator, prefix) {
192 getLocator := locator
193 if blobSigningKey != "" {
194 expiresAt := time.Now().AddDate(0, 0, 1)
195 getLocator = keepclient.SignLocator(locator, kc.Arvados.ApiToken, expiresAt, []byte(blobSigningKey))
198 _, _, err := kc.Ask(getLocator)
200 log.Printf("Error getting head info for block: %v %v", locator, err)