├── LICENSE ├── README.md ├── airbyte ├── api │ ├── api_connections.go │ ├── api_destinations.go │ ├── api_jobs.go │ ├── api_scheduler.go │ ├── api_source_definitions.go │ ├── api_sources.go │ ├── api_workspace.go │ └── variables.go ├── connections.go ├── destinations.go ├── jobs.go ├── sources.go ├── utils_output.go └── workspaces.go ├── cmd ├── check │ ├── check.go │ └── check_source.go ├── create │ ├── create.go │ ├── create_connection.go │ ├── create_destination.go │ └── create_sources.go ├── export │ └── export.go ├── get │ ├── get.go │ ├── get_connections.go │ ├── get_destinations.go │ ├── get_jobs.go │ ├── get_source_definitions.go │ ├── get_sources.go │ └── get_workspaces.go ├── logs.go ├── root.go ├── search │ ├── search.go │ ├── search_connections.go │ └── search_sources.go └── set.go ├── common ├── api_utils.go ├── tar_utils.go └── url_utils.go ├── go.mod ├── go.sum ├── logger └── logger.go ├── main.go └── models ├── common.go ├── connections.go ├── destinations.go ├── jobs.go ├── sources.go └── workspace.go /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deprecated. Airbyte launched octavia-cli which is Airbyte own cli 2 | 3 | # Airbyte CLI 4 | 5 | This is the next generation Go based Airbyte CLI. 6 | 7 | ## Contents 8 | - [Setup](#setup) 9 | - [Configuration as YAML](#configuration-as-yaml) 10 | - [Usage](#usage) 11 | - [get](#get) 12 | - [search](#search) 13 | - [check](#check) 14 | - [logs](#logs) 15 | - [export](#export) 16 | - [create](#create) 17 | 18 | ## Setup 19 | 1. Clone this repo to your working environment 20 | `git clone https://github.com/harshithmullapudi/airbyte-cli.git` 21 | 2. Install go (if not installed already). 22 | `brew install go` (for mac users) 23 | 3. Jump to the airbyte-cli directory and run 24 | `go install .` 25 | 4. You're all set to fly 26 | 27 | ## Configuration as YAML 28 | Before we interact with Airbyte API, we need to set Airbyte API URL and workspace, for which you can use the following command 29 | ```bash 30 | $ airbyte set-config 31 | ``` 32 | 33 | ## Usage 34 | An Airbyte CLI command has the following structure: 35 | ```bash 36 | $ airbyte [options and parameters] 37 | ``` 38 | ``` 39 | 40 | get - Get configuration of Sources/Destinations/Connections 41 | search - Search in sources 42 | check - Check connection to Source/Destination 43 | logs - Fetch logs for a job 44 | set-config - Set your airbyte url and workspaceID 45 | help - Help about any command 46 | ``` 47 | To view help documentation, use one of the following: 48 | ```bash 49 | $ airbyte -h 50 | $ airbyte -h 51 | $ airbyte -h 52 | ``` 53 | ## get 54 | Return all 55 | - workspaces (`/v1/workspaces/list`) 56 | - sources (`/v1/sources/list`) 57 | - destinations (`/v1/destinations/list`) 58 | - connections (`/v1/web_backend/connections/list`) 59 | 60 | You can use page(p) and offset(o) to fetch sources respectively. 61 | 62 | To list workspaces, the command would be: 63 | ```bash 64 | $ airbyte get workspaces 65 | ``` 66 | To get a workspace, the command would be: 67 | ```bash 68 | $ airbyte get workspace [workspaceId] 69 | ``` 70 | To list sources, the command would be: 71 | ```bash 72 | $ airbyte get sources 73 | ``` 74 | To get a source, the command would be: 75 | ```bash 76 | $ airbyte get source [sourceId] 77 | ``` 78 | To get jobs for a connection, the command would be: 79 | ```bash 80 | $ airbyte get jobs [connectionId] 81 | ``` 82 | 83 | ## search 84 | - sources 85 | - connections 86 | 87 | To search in sources, the command would be: 88 | ```bash 89 | $ airbyte search sources [string] 90 | ``` 91 | 92 | ## check 93 | Validate 94 | - source (`/v1/sources/check_connection`) 95 | - destination (`/v1/destinations/check_connection`) 96 | 97 | To validate a source, the command would be: 98 | ```bash 99 | $ airbyte check source [sourceId] 100 | ``` 101 | 102 | ## logs 103 | Get logs for a job 104 | ```bash 105 | $ airbyte logs [jobId] 106 | ``` 107 | 108 | ## export 109 | Export sources, connections and destinations to a target folder 110 | ```bash 111 | $ airbyte export -t [absolute path to target folder] 112 | ``` 113 | 114 | ## create 115 | 116 | You can create and validation sources, destinations and connections through a yaml file. 117 | 118 | 1. Create a folder in your home example: /Users/name/home/load 119 | 2. Create a yaml file SOURCE_CONNECTION.yaml for sources, DESTINATION_CONNECTION.yaml for destinations and STANDARD_SYNC.yaml for connections 120 | 3. Hurray 121 | 122 | ```bash 123 | $ airbyte create -f /Users/name/home/load -c 124 | ``` 125 | 126 | 127 | Validate sources, destinations and connections before creation 128 | ```bash 129 | $ airbyte create -f [path to config folder] 130 | ``` 131 | 132 | You can pass -c as a flag to create the sources which will validate the source and skip it either if validation failes or if it finds sourceId and 133 | a source for that respective Id. 134 | 135 | ```bash 136 | $ airbyte create -f [path to config folder] 137 | ``` 138 | -------------------------------------------------------------------------------- /airbyte/api/api_connections.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/harshithmullapudi/airbyte/common" 7 | "github.com/harshithmullapudi/airbyte/models" 8 | "github.com/spf13/viper" 9 | ) 10 | 11 | // Get Connections - /api/v1/web_backend/connections/list 12 | func GetConnections() (models.Connections, error) { 13 | var API_URL string = common.GetFullApiURL(GET_CONNECTIONS) 14 | 15 | workspaceId := viper.GetString("workspace_id") 16 | 17 | respBody, err := common.ApiCall(API_URL, map[string]string{ 18 | "workspaceId": workspaceId, 19 | }) 20 | 21 | //Handle Error 22 | if err != nil { 23 | return models.Connections{}, err 24 | } 25 | 26 | var connectionResponse models.ConnectionResponse 27 | json.Unmarshal(respBody, &connectionResponse) 28 | 29 | return connectionResponse.Connections, nil 30 | } 31 | 32 | // Get Connection - /api/v1/web_backend/connections/get 33 | func GetConnection(connectionId string) (models.Connection, error) { 34 | var API_URL string = common.GetFullApiURL(GET_CONNECTION) 35 | 36 | respBody, err := common.ApiCall(API_URL, map[string]string{ 37 | "connectionId": connectionId, 38 | }) 39 | 40 | //Handle Error 41 | if err != nil { 42 | return models.Connection{}, err 43 | } 44 | 45 | var connectionResponse models.Connection 46 | json.Unmarshal(respBody, &connectionResponse) 47 | 48 | return connectionResponse, nil 49 | } 50 | 51 | func CreateConnection(connection models.ConnectionShort) (models.ConnectionShort, error) { 52 | var API_URL string = common.GetFullApiURL(CREATE_CONNECTION) 53 | 54 | var schedule interface{} 55 | 56 | schedule = connection.Schedule 57 | 58 | if connection.Manual { 59 | schedule = nil 60 | } 61 | 62 | respBody, err := common.ApiCallInterface(API_URL, map[interface{}]interface{}{ 63 | "name": connection.Name, 64 | "prefix": connection.Prefix, 65 | "sourceId": connection.SourceId, 66 | "destinationId": connection.DestinationId, 67 | "syncCatalog": connection.Catalog, 68 | "schedule": schedule, 69 | "status": connection.Status, 70 | }) 71 | 72 | var connectionResponse models.ConnectionShort 73 | json.Unmarshal(respBody, &connectionResponse) 74 | 75 | if err != nil { 76 | return models.ConnectionShort{}, err 77 | } 78 | 79 | return connectionResponse, nil 80 | } 81 | -------------------------------------------------------------------------------- /airbyte/api/api_destinations.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/harshithmullapudi/airbyte/common" 7 | "github.com/harshithmullapudi/airbyte/models" 8 | "github.com/spf13/viper" 9 | ) 10 | 11 | func GetDestionations() (models.Destinations, error) { 12 | 13 | var API_URL string = common.GetFullApiURL(GET_DESTINATIONS) 14 | 15 | workspaceId := viper.GetString("workspace_id") 16 | 17 | respBody, err := common.ApiCall(API_URL, map[string]string{ 18 | "workspaceId": workspaceId, 19 | }) 20 | 21 | //Handle Error 22 | if err != nil { 23 | return models.Destinations{}, err 24 | } 25 | 26 | var destinationResponse models.DestinationResponse 27 | json.Unmarshal(respBody, &destinationResponse) 28 | 29 | return destinationResponse.Destinations, nil 30 | } 31 | 32 | func GetDestination(destinationId string) (models.Destination, error) { 33 | 34 | var API_URL string = common.GetFullApiURL(GET_DESTINATION) 35 | 36 | respBody, err := common.ApiCall(API_URL, map[string]string{ 37 | "destinationId": destinationId, 38 | }) 39 | 40 | //Handle Error 41 | if err != nil { 42 | return models.Destination{}, err 43 | } 44 | 45 | var destinationResponse models.Destination 46 | json.Unmarshal(respBody, &destinationResponse) 47 | 48 | return destinationResponse, nil 49 | } 50 | 51 | // Create Destination 52 | func CreateDestination(destination models.Destination) (models.Destination, error) { 53 | var API_URL string = common.GetFullApiURL(CREATE_DESTINATION) 54 | 55 | var workspaceId string 56 | 57 | _, err := CheckIfWorkspaceExist(destination.WorkspaceId) 58 | 59 | workspaceId = destination.WorkspaceId 60 | 61 | if err != nil { 62 | workspaceId = viper.GetString("workspace_id") 63 | } 64 | 65 | respBody, err := common.ApiCallInterface(API_URL, map[interface{}]interface{}{ 66 | "destinationDefinitionId": destination.DestinationDefinitionId, 67 | "connectionConfiguration": destination.ConnectionConfiguration, 68 | "workspaceId": workspaceId, 69 | "name": destination.Name, 70 | }) 71 | 72 | var destinationResponse models.Destination 73 | json.Unmarshal(respBody, &destinationResponse) 74 | 75 | if err != nil { 76 | return models.Destination{}, err 77 | } 78 | 79 | return destinationResponse, nil 80 | } 81 | -------------------------------------------------------------------------------- /airbyte/api/api_jobs.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "io/ioutil" 7 | "net/http" 8 | 9 | "github.com/harshithmullapudi/airbyte/common" 10 | "github.com/harshithmullapudi/airbyte/models" 11 | ) 12 | 13 | func GetJobs(configId string, configType string) (models.Jobs, error) { 14 | var API_URL string = common.GetFullApiURL(GET_JOBS) 15 | var configTypes []string 16 | 17 | configTypes = append(configTypes, configType) 18 | 19 | postBody, _ := json.Marshal(map[string]interface{}{ 20 | "configTypes": configTypes, 21 | "configId": configId, 22 | }) 23 | 24 | requestBody := bytes.NewBuffer(postBody) 25 | 26 | //Leverage Go's HTTP Post function to make request 27 | resp, err := http.Post(API_URL, "application/json", requestBody) 28 | 29 | //Handle Error 30 | if err != nil { 31 | return models.Jobs{}, err 32 | } 33 | 34 | defer resp.Body.Close() 35 | 36 | //Read the response body 37 | body, err := ioutil.ReadAll(resp.Body) 38 | if err != nil { 39 | return models.Jobs{}, err 40 | } 41 | 42 | var jobsResponse models.JobsResponse 43 | json.Unmarshal(body, &jobsResponse) 44 | 45 | return jobsResponse.Jobs, nil 46 | } 47 | 48 | func GetJob(jobId int) (models.GetJobResponse, error) { 49 | var API_URL string = common.GetFullApiURL(GET_JOB) 50 | 51 | postBody, _ := json.Marshal(map[string]interface{}{ 52 | "id": jobId, 53 | }) 54 | 55 | requestBody := bytes.NewBuffer(postBody) 56 | 57 | //Leverage Go's HTTP Post function to make request 58 | resp, err := http.Post(API_URL, "application/json", requestBody) 59 | 60 | //Handle Error 61 | if err != nil { 62 | return models.GetJobResponse{}, err 63 | } 64 | 65 | defer resp.Body.Close() 66 | 67 | //Read the response body 68 | body, err := ioutil.ReadAll(resp.Body) 69 | if err != nil { 70 | return models.GetJobResponse{}, err 71 | } 72 | 73 | var jobsResponse models.GetJobResponse 74 | json.Unmarshal(body, &jobsResponse) 75 | 76 | return jobsResponse, nil 77 | } 78 | -------------------------------------------------------------------------------- /airbyte/api/api_scheduler.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/harshithmullapudi/airbyte/common" 7 | "github.com/harshithmullapudi/airbyte/models" 8 | ) 9 | 10 | func SourceConnectionCheckSchedule(source models.Source) (models.SourceCheckResponse, error) { 11 | var API_URL string = common.GetFullApiURL(SOURCE_CONNECTION_CHECK) 12 | respBody, err := common.ApiCallInterface(API_URL, map[interface{}]interface{}{ 13 | "sourceDefinitionId": source.SourceDefinitionId, 14 | "connectionConfiguration": source.ConnectionConfiguration, 15 | }) 16 | 17 | var sourceCheckResponse models.SourceCheckResponse 18 | json.Unmarshal(respBody, &sourceCheckResponse) 19 | 20 | if err != nil { 21 | return models.SourceCheckResponse{}, err 22 | } 23 | 24 | return sourceCheckResponse, nil 25 | } 26 | 27 | func DestinationConnectionCheckSchedule(destination models.Destination) (models.CheckResponse, error) { 28 | var API_URL string = common.GetFullApiURL(DESTINATION_CONNECTION_CHECK) 29 | respBody, err := common.ApiCallInterface(API_URL, map[interface{}]interface{}{ 30 | "destinationDefinitionId": destination.DestinationDefinitionId, 31 | "connectionConfiguration": destination.ConnectionConfiguration, 32 | }) 33 | 34 | var destinationCheckResponse models.CheckResponse 35 | json.Unmarshal(respBody, &destinationCheckResponse) 36 | 37 | if err != nil { 38 | return models.CheckResponse{}, err 39 | } 40 | 41 | return destinationCheckResponse, nil 42 | } 43 | -------------------------------------------------------------------------------- /airbyte/api/api_source_definitions.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/harshithmullapudi/airbyte/common" 7 | "github.com/harshithmullapudi/airbyte/models" 8 | ) 9 | 10 | func GetSourceDefinitions() (models.SourceDefinitions, error) { 11 | var API_URL string = common.GetFullApiURL(GET_SOURCE_DEFINITIONS) 12 | 13 | respBody, err := common.ApiCall(API_URL, nil) 14 | 15 | //Handle Error 16 | if err != nil { 17 | return models.SourceDefinitions{}, err 18 | } 19 | 20 | var sourceDefinitionResponse models.SourceDefinitionResponse 21 | json.Unmarshal(respBody, &sourceDefinitionResponse) 22 | 23 | return sourceDefinitionResponse.SourceDefinitions, nil 24 | } 25 | -------------------------------------------------------------------------------- /airbyte/api/api_sources.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/harshithmullapudi/airbyte/common" 7 | "github.com/harshithmullapudi/airbyte/models" 8 | "github.com/spf13/viper" 9 | ) 10 | 11 | // Get Connections - /api/v1/sources/list 12 | func GetSources() (models.Sources, error) { 13 | 14 | var API_URL string = common.GetFullApiURL(GET_SOURCES) 15 | 16 | workspaceId := viper.GetString("workspace_id") 17 | 18 | respBody, err := common.ApiCall(API_URL, map[string]string{ 19 | "workspaceId": workspaceId, 20 | }) 21 | 22 | //Handle Error 23 | if err != nil { 24 | return models.Sources{}, err 25 | } 26 | 27 | var sourceResponse models.SourceResponse 28 | json.Unmarshal(respBody, &sourceResponse) 29 | 30 | return sourceResponse.Sources, nil 31 | } 32 | 33 | // Get Connection - /api/v1/sources/get 34 | func GetSource(sourceId string) (models.Source, error) { 35 | 36 | var API_URL string = common.GetFullApiURL(GET_SOURCE) 37 | 38 | respBody, err := common.ApiCall(API_URL, map[string]string{ 39 | "sourceId": sourceId, 40 | }) 41 | 42 | if err != nil { 43 | return models.Source{}, err 44 | } 45 | 46 | var sourceResponse models.Source 47 | json.Unmarshal(respBody, &sourceResponse) 48 | 49 | return sourceResponse, nil 50 | } 51 | 52 | // Check Source Connection - /api/v1/sources/check_connection 53 | func CheckSourceConnection(sourceId string) (models.SourceCheckResponse, error) { 54 | var API_URL string = common.GetFullApiURL(SOURCE_CHECK_CONNECTION) 55 | 56 | respBody, err := common.ApiCall(API_URL, map[string]string{ 57 | "sourceId": sourceId, 58 | }) 59 | 60 | if err != nil { 61 | return models.SourceCheckResponse{}, err 62 | } 63 | 64 | var sourceCheckResponse models.SourceCheckResponse 65 | json.Unmarshal(respBody, &sourceCheckResponse) 66 | 67 | return sourceCheckResponse, nil 68 | } 69 | 70 | // Create Source 71 | func CreateSource(source models.Source) (models.Source, error) { 72 | var API_URL string = common.GetFullApiURL(CREATE_SOURCE) 73 | 74 | var workspaceId string 75 | 76 | _, err := CheckIfWorkspaceExist(source.WorkspaceId) 77 | 78 | workspaceId = source.WorkspaceId 79 | 80 | if err != nil { 81 | workspaceId = viper.GetString("workspace_id") 82 | } 83 | 84 | respBody, err := common.ApiCallInterface(API_URL, map[interface{}]interface{}{ 85 | "sourceDefinitionId": source.SourceDefinitionId, 86 | "connectionConfiguration": source.ConnectionConfiguration, 87 | "workspaceId": workspaceId, 88 | "name": source.Name, 89 | }) 90 | 91 | var sourceResponse models.Source 92 | json.Unmarshal(respBody, &sourceResponse) 93 | 94 | if err != nil { 95 | return models.Source{}, err 96 | } 97 | 98 | return sourceResponse, nil 99 | } 100 | -------------------------------------------------------------------------------- /airbyte/api/api_workspace.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "io/ioutil" 7 | "net/http" 8 | 9 | "github.com/harshithmullapudi/airbyte/common" 10 | "github.com/harshithmullapudi/airbyte/models" 11 | ) 12 | 13 | // Get Workspaces - /v1/workspaces/list 14 | func GetWorkspaces() (models.Workspaces, error) { 15 | 16 | var API_URL string = common.GetFullApiURL(GET_WORKSPACES) 17 | 18 | respBody, err := common.ApiCall(API_URL, map[string]string{}) 19 | 20 | //Handle Error 21 | if err != nil { 22 | return models.Workspaces{}, err 23 | } 24 | 25 | var workspaceResponse models.WorkspaceResponse 26 | json.Unmarshal(respBody, &workspaceResponse) 27 | 28 | return workspaceResponse.Workspaces, nil 29 | } 30 | 31 | // Get Connection - /api/v1/workspaces/get 32 | func GetWorkspace(workspaceId string) (models.Workspace, error) { 33 | 34 | //Get First Workspace 35 | if workspaceId == "" { 36 | workspaces, err := GetWorkspaces() 37 | 38 | //Handle Error 39 | if err != nil { 40 | return models.Workspace{}, err 41 | } 42 | 43 | workspaceId = workspaces[0].WorkspaceId 44 | } 45 | 46 | var API_URL string = common.GetFullApiURL(GET_WORKSPACE) 47 | 48 | respBody, err := common.ApiCall(API_URL, map[string]string{ 49 | "workspaceId": workspaceId, 50 | }) 51 | 52 | if err != nil { 53 | return models.Workspace{}, err 54 | } 55 | 56 | var workspaceResponse models.Workspace 57 | json.Unmarshal(respBody, &workspaceResponse) 58 | 59 | return workspaceResponse, nil 60 | } 61 | 62 | func CheckIfWorkspaceExist(workspaceId string) (models.Workspace, error) { 63 | var API_URL string = common.GetFullApiURL(GET_WORKSPACE) 64 | 65 | postBody, _ := json.Marshal(map[string]string{ 66 | "workspaceId": workspaceId, 67 | }) 68 | 69 | requestBody := bytes.NewBuffer(postBody) 70 | 71 | //Leverage Go's HTTP Post function to make request 72 | resp, err := http.Post(API_URL, "application/json", requestBody) 73 | 74 | //Handle Error 75 | if err != nil { 76 | return models.Workspace{}, err 77 | } 78 | 79 | defer resp.Body.Close() 80 | 81 | //Read the response body 82 | body, err := ioutil.ReadAll(resp.Body) 83 | if err != nil { 84 | return models.Workspace{}, err 85 | } 86 | 87 | var workspace models.Workspace 88 | json.Unmarshal(body, &workspace) 89 | 90 | return workspace, nil 91 | } 92 | -------------------------------------------------------------------------------- /airbyte/api/variables.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | var SOURCES = "/api/v1/sources" 4 | var SOURCE_DEFINITIONS = "/api/v1/source_definitions" 5 | var WORKSPACES = "/api/v1/workspaces" 6 | var CONNECTIONS = "/api/v1/web_backend/connections" 7 | var JOBS = "/api/v1/jobs" 8 | var DESTINATIONS = "/api/v1/destinations" 9 | 10 | var GET_WORKSPACES = WORKSPACES + "/list" 11 | var GET_WORKSPACE = WORKSPACES + "/get" 12 | 13 | var CREATE_SOURCE = SOURCES + "/create" 14 | var GET_SOURCES = SOURCES + "/list" 15 | var GET_SOURCE = SOURCES + "/get" 16 | var SOURCE_CHECK_CONNECTION = SOURCES + "/check_connection" 17 | 18 | var CREATE_CONNECTION = CONNECTIONS + "/create" 19 | var GET_CONNECTIONS = CONNECTIONS + "/list" 20 | var GET_CONNECTION = CONNECTIONS + "/get" 21 | 22 | var GET_JOBS = JOBS + "/list" 23 | var GET_JOB = JOBS + "/get" 24 | 25 | var CREATE_DESTINATION = DESTINATIONS + "/create" 26 | var GET_DESTINATIONS = DESTINATIONS + "/list" 27 | var GET_DESTINATION = DESTINATIONS + "/get" 28 | 29 | var GET_SOURCE_DEFINITIONS = SOURCE_DEFINITIONS + "/list" 30 | 31 | var DOWNLOAD_CONFIG = "/api/v1/deployment/export" 32 | 33 | var SOURCE_CONNECTION_CHECK = "/api/v1/scheduler/sources/check_connection" 34 | var DESTINATION_CONNECTION_CHECK = "/api/v1/scheduler/destinations/check_connection" 35 | -------------------------------------------------------------------------------- /airbyte/connections.go: -------------------------------------------------------------------------------- 1 | package airbyte 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "math" 7 | "strings" 8 | 9 | "github.com/harshithmullapudi/airbyte/airbyte/api" 10 | "github.com/harshithmullapudi/airbyte/logger" 11 | "github.com/harshithmullapudi/airbyte/models" 12 | ) 13 | 14 | func PaginateConnections(offset int, number int, status string) (models.Connections, error) { 15 | connections, _ := api.GetConnections() 16 | logger.Log.Info("Fetching connections from API with offset: " + fmt.Sprintf("%d", offset)) 17 | logger.Log.Info("Total connections: " + fmt.Sprintf("%d", len(connections))) 18 | 19 | var filteredConnections models.Connections 20 | 21 | // filter status attribute 22 | if status == "" { 23 | filteredConnections = connections 24 | } else { 25 | for _, c := range connections { 26 | if c.Status == status { 27 | filteredConnections = append(filteredConnections, c) 28 | } 29 | } 30 | } 31 | 32 | var endIndex int = int(math.Min(float64(offset+number), float64(len(filteredConnections)))) 33 | 34 | var finalConnections models.Connections = filteredConnections[offset:endIndex] 35 | return finalConnections, nil 36 | } 37 | 38 | func FetchConnection(connectionId string) (models.Connection, error) { 39 | logger.Log.Info("Fetching connection from API for connectionId: " + connectionId) 40 | 41 | connection, err := api.GetConnection(connectionId) 42 | 43 | return connection, err 44 | } 45 | 46 | // Search in connections from a given string 47 | func SearchConnection(searchString string) (models.Connections, error) { 48 | if searchString == "" { 49 | return models.Connections{}, errors.New("you passed an empty string") 50 | } 51 | 52 | connections, _ := api.GetConnections() 53 | var filteredConnections models.Connections 54 | 55 | for _, c := range connections { 56 | if strings.Contains(strings.ToLower(c.Source.Name), strings.ToLower(searchString)) { 57 | filteredConnections = append(filteredConnections, c) 58 | } 59 | } 60 | 61 | return filteredConnections, nil 62 | } 63 | -------------------------------------------------------------------------------- /airbyte/destinations.go: -------------------------------------------------------------------------------- 1 | package airbyte 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | 7 | "github.com/harshithmullapudi/airbyte/airbyte/api" 8 | "github.com/harshithmullapudi/airbyte/logger" 9 | "github.com/harshithmullapudi/airbyte/models" 10 | ) 11 | 12 | func PaginateDestinations(offset int, number int) (models.Destinations, error) { 13 | destinations, _ := api.GetDestionations() 14 | logger.Log.Info("Fetching sources from API with offset: " + fmt.Sprintf("%d", offset)) 15 | logger.Log.Info("Total sources: " + fmt.Sprintf("%d", len(destinations))) 16 | 17 | var endIndex int = int(math.Min(float64(offset+number), float64(len(destinations)))) 18 | 19 | var finalDestinations models.Destinations = destinations[offset:endIndex] 20 | return finalDestinations, nil 21 | } 22 | 23 | func FetchDestination(destinationId string) (models.Destination, error) { 24 | logger.Log.Info("Fetching destination from API for destinationId: " + destinationId) 25 | 26 | destination, err := api.GetDestination(destinationId) 27 | return destination, err 28 | } 29 | -------------------------------------------------------------------------------- /airbyte/jobs.go: -------------------------------------------------------------------------------- 1 | package airbyte 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/harshithmullapudi/airbyte/airbyte/api" 7 | "github.com/harshithmullapudi/airbyte/logger" 8 | "github.com/harshithmullapudi/airbyte/models" 9 | ) 10 | 11 | func PaginateJobs(configId string, configType string) (models.Jobs, error) { 12 | logger.Log.Info("Fetching jobs from API for connection " + configId) 13 | logger.Log.Info("With Config Type: " + configType) 14 | jobs, _ := api.GetJobs(configId, configType) 15 | logger.Log.Info("Total jobs: " + fmt.Sprintf("%d", len(jobs))) 16 | 17 | return jobs, nil 18 | } 19 | 20 | func FetchJob(jobId int) (models.GetJobResponse, error) { 21 | logger.Log.Info("Fetching job from API for id " + fmt.Sprint(jobId)) 22 | job, _ := api.GetJob(jobId) 23 | 24 | return job, nil 25 | } 26 | -------------------------------------------------------------------------------- /airbyte/sources.go: -------------------------------------------------------------------------------- 1 | package airbyte 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "math" 7 | "strings" 8 | 9 | "github.com/harshithmullapudi/airbyte/airbyte/api" 10 | "github.com/harshithmullapudi/airbyte/logger" 11 | "github.com/harshithmullapudi/airbyte/models" 12 | ) 13 | 14 | func PaginateSources(offset int, number int) (models.Sources, error) { 15 | sources, _ := api.GetSources() 16 | logger.Log.Info("Fetching sources from API with offset: " + fmt.Sprintf("%d", offset)) 17 | logger.Log.Info("Total sources: " + fmt.Sprintf("%d", len(sources))) 18 | 19 | var endIndex int = int(math.Min(float64(offset+number), float64(len(sources)))) 20 | 21 | var finalSources models.Sources = sources[offset:endIndex] 22 | return finalSources, nil 23 | } 24 | 25 | func FetchSource(sourceId string) (models.Source, error) { 26 | logger.Log.Info("Fetching source from API for sourceId: " + sourceId) 27 | 28 | source, err := api.GetSource(sourceId) 29 | return source, err 30 | } 31 | 32 | func SearchSource(searchString string) (models.Sources, error) { 33 | if searchString == "" { 34 | return models.Sources{}, errors.New("you passed an empty string") 35 | } 36 | 37 | sources, _ := api.GetSources() 38 | var filteredSources models.Sources 39 | 40 | for _, s := range sources { 41 | if strings.Contains(strings.ToLower(s.Name), strings.ToLower(searchString)) { 42 | filteredSources = append(filteredSources, s) 43 | } 44 | } 45 | 46 | return filteredSources, nil 47 | } 48 | -------------------------------------------------------------------------------- /airbyte/utils_output.go: -------------------------------------------------------------------------------- 1 | package airbyte 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "os" 7 | "time" 8 | 9 | "github.com/harshithmullapudi/airbyte/logger" 10 | "github.com/harshithmullapudi/airbyte/models" 11 | "github.com/jedib0t/go-pretty/v6/table" 12 | ) 13 | 14 | //Sources Print 15 | func PrintSourcesTable(sources models.Sources) { 16 | t := table.NewWriter() 17 | t.SetOutputMirror(os.Stdout) 18 | t.AppendHeader(table.Row{"#", "Source Definition Id", "Source Id", "Name", "Source Name"}) 19 | for index, s := range sources { 20 | t.AppendRow([]interface{}{index + 1, s.SourceDefinitionId, s.SourceId, s.Name, s.SourceName}) 21 | } 22 | t.Render() 23 | } 24 | 25 | func PrintSourceTable(source models.Source) { 26 | t := table.NewWriter() 27 | t.SetOutputMirror(os.Stdout) 28 | t.AppendHeader(table.Row{"#", "Source Definition Id", "Source Id", "Name", "Source Name"}) 29 | 30 | t.AppendRow([]interface{}{1, source.SourceDefinitionId, source.SourceId, source.Name, source.SourceName}) 31 | 32 | t.Render() 33 | } 34 | 35 | func PrintSources(sources models.Sources) { 36 | 37 | b, err := json.MarshalIndent(sources, "", " ") 38 | 39 | if err != nil { 40 | logger.Error(err) 41 | return 42 | } 43 | 44 | fmt.Println(string(b)) 45 | } 46 | 47 | func PrintSource(source models.Source) { 48 | 49 | b, err := json.MarshalIndent(source, "", " ") 50 | 51 | if err != nil { 52 | logger.Error(err) 53 | return 54 | } 55 | 56 | fmt.Println(string(b)) 57 | } 58 | 59 | // Print Destinations 60 | func PrintDestinationsTable(destinations models.Destinations) { 61 | t := table.NewWriter() 62 | t.SetOutputMirror(os.Stdout) 63 | t.AppendHeader(table.Row{"#", "Destination Definition Id", "Destination Id", "Name", "Destination Name"}) 64 | for index, d := range destinations { 65 | t.AppendRow([]interface{}{index + 1, d.DestinationDefinitionId, d.DestinationId, d.Name, d.DestinationName}) 66 | } 67 | t.Render() 68 | } 69 | 70 | func PrintDestinationTable(destination models.Destination) { 71 | t := table.NewWriter() 72 | t.SetOutputMirror(os.Stdout) 73 | t.AppendHeader(table.Row{"#", "Destination Definition Id", "Destination Id", "Name", "Destination Name"}) 74 | 75 | t.AppendRow([]interface{}{1, destination.DestinationDefinitionId, destination.DestinationId, destination.Name, destination.DestinationName}) 76 | 77 | t.Render() 78 | } 79 | 80 | func PrintDestinations(destinations models.Destinations) { 81 | 82 | b, err := json.MarshalIndent(destinations, "", " ") 83 | 84 | if err != nil { 85 | logger.Error(err) 86 | return 87 | } 88 | 89 | fmt.Println(string(b)) 90 | } 91 | 92 | func PrintDestination(destination models.Destination) { 93 | 94 | b, err := json.MarshalIndent(destination, "", " ") 95 | 96 | if err != nil { 97 | logger.Error(err) 98 | return 99 | } 100 | 101 | fmt.Println(string(b)) 102 | } 103 | 104 | //Connections print 105 | func PrintConnectionsTable(connections models.Connections) { 106 | t := table.NewWriter() 107 | t.SetOutputMirror(os.Stdout) 108 | t.AppendHeader(table.Row{"#", "Connection Id", "Source Id", "Name", "Source Name", "Destination Id", "Schedule", "Status", "Sync Status"}) 109 | for index, c := range connections { 110 | t.AppendRow([]interface{}{index + 1, c.ConnectionId, c.SourceId, c.Source.Name, c.Source.SourceName, c.DestinationId, c.Schedule, c.Status, c.LatestSyncJobStatus}) 111 | } 112 | t.Render() 113 | } 114 | 115 | func PrintConnectionTable(connection models.Connection) { 116 | t := table.NewWriter() 117 | t.SetOutputMirror(os.Stdout) 118 | t.AppendHeader(table.Row{"#", "Connection Id", "Source Id", "Name", "Source Name", "Destination Id", "Schedule", "Status", "Sync Status"}) 119 | t.AppendRow([]interface{}{1, connection.ConnectionId, connection.SourceId, connection.Source.Name, connection.Source.SourceName, connection.DestinationId, connection.Schedule, connection.Status, connection.LatestSyncJobStatus}) 120 | t.Render() 121 | } 122 | 123 | func PrintConnections(connections models.Connections) { 124 | 125 | b, err := json.MarshalIndent(connections, "", " ") 126 | 127 | if err != nil { 128 | logger.Error(err) 129 | return 130 | } 131 | 132 | fmt.Println(string(b)) 133 | } 134 | 135 | func PrintConnection(connection models.Connection) { 136 | 137 | b, err := json.MarshalIndent(connection, "", " ") 138 | 139 | if err != nil { 140 | logger.Error(err) 141 | return 142 | } 143 | 144 | fmt.Println(string(b)) 145 | } 146 | 147 | // Print Jobs 148 | func PrintJobsTable(jobs models.Jobs) { 149 | t := table.NewWriter() 150 | t.SetOutputMirror(os.Stdout) 151 | t.AppendHeader(table.Row{"#", "Job Id", "Config Id", "Config Type", "Created At", "Status", "Total Attempts", "Records Synced"}) 152 | for index, j := range jobs { 153 | var attemtStatus models.Attempt 154 | for _, a := range j.Attempts { 155 | if a.Status == "succeeded" { 156 | attemtStatus = a 157 | } 158 | } 159 | 160 | unixTimeUTC := time.Unix(j.Job.CreatedAt, 0) 161 | unitTimeInRFC3339 := unixTimeUTC.Format(time.RFC3339) 162 | 163 | t.AppendRow([]interface{}{index + 1, j.Job.Id, j.Job.ConfigId, j.Job.ConfigType, unitTimeInRFC3339, j.Job.Status, len(j.Attempts), attemtStatus.RecordsSynced}) 164 | } 165 | t.Render() 166 | } 167 | 168 | func PrintJobTable(job models.GetJobResponse) { 169 | t := table.NewWriter() 170 | t.SetOutputMirror(os.Stdout) 171 | t.AppendHeader(table.Row{"#", "Job Id", "Config Id", "Config Type", "Created At", "Status", "Total Attempts", "Records Synced"}) 172 | var attemtStatus models.Attempt 173 | for _, a := range job.Attempts { 174 | if a.Attempt.Status == "succeeded" { 175 | attemtStatus = a.Attempt 176 | } 177 | } 178 | 179 | unixTimeUTC := time.Unix(job.Job.CreatedAt, 0) 180 | unitTimeInRFC3339 := unixTimeUTC.Format(time.RFC3339) 181 | 182 | t.AppendRow([]interface{}{1, job.Job.Id, job.Job.ConfigId, job.Job.ConfigType, unitTimeInRFC3339, job.Job.Status, len(job.Attempts), attemtStatus.RecordsSynced}) 183 | t.Render() 184 | } 185 | 186 | // Print Source Definition 187 | func PrintSourceDefinitionsTable(source_definitions models.SourceDefinitions) { 188 | t := table.NewWriter() 189 | t.SetOutputMirror(os.Stdout) 190 | t.AppendHeader(table.Row{"#", "Source Definition Id", "Name", "Docker Repository", "Docker Image Tag"}) 191 | for index, sd := range source_definitions { 192 | t.AppendRow([]interface{}{index + 1, sd.SourceDefinitionId, sd.Name, sd.DockerRepository, sd.DockerImageTag}) 193 | } 194 | t.Render() 195 | } 196 | 197 | //Print Workspaces 198 | func PrintWorkspacesTable(workspaces models.Workspaces) { 199 | t := table.NewWriter() 200 | t.SetOutputMirror(os.Stdout) 201 | t.AppendHeader(table.Row{"#", "Workspace ID", "Workspace Name", "Email", "Slug"}) 202 | for index, w := range workspaces { 203 | t.AppendRow([]interface{}{index + 1, w.WorkspaceId, w.Name, w.Email, w.Slug}) 204 | } 205 | t.Render() 206 | } 207 | 208 | func PrintWorkspaceTable(workspace models.Workspace) { 209 | t := table.NewWriter() 210 | t.SetOutputMirror(os.Stdout) 211 | t.AppendHeader(table.Row{"#", "Workspace ID", "Workspace Name", "Email", "Slug"}) 212 | 213 | t.AppendRow([]interface{}{1, workspace.WorkspaceId, workspace.Name, workspace.Email, workspace.Slug}) 214 | 215 | t.Render() 216 | } 217 | 218 | func PrintWorkspaces(workspaces models.Workspaces) { 219 | 220 | b, err := json.MarshalIndent(workspaces, "", " ") 221 | 222 | if err != nil { 223 | logger.Error(err) 224 | return 225 | } 226 | 227 | fmt.Println(string(b)) 228 | } 229 | 230 | func PrintWorkspace(workspace models.Workspace) { 231 | 232 | b, err := json.MarshalIndent(workspace, "", " ") 233 | 234 | if err != nil { 235 | logger.Error(err) 236 | return 237 | } 238 | 239 | fmt.Println(string(b)) 240 | } 241 | -------------------------------------------------------------------------------- /airbyte/workspaces.go: -------------------------------------------------------------------------------- 1 | package airbyte 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "math" 7 | "strings" 8 | 9 | "github.com/harshithmullapudi/airbyte/airbyte/api" 10 | "github.com/harshithmullapudi/airbyte/logger" 11 | "github.com/harshithmullapudi/airbyte/models" 12 | ) 13 | 14 | func PaginateWorkspaces(offset int, number int) (models.Workspaces, error) { 15 | workspaces, _ := api.GetWorkspaces() 16 | logger.Log.Info("Fetching workspaces from API with offset: " + fmt.Sprintf("%d", offset)) 17 | logger.Log.Info("Total workspaces: " + fmt.Sprintf("%d", len(workspaces))) 18 | 19 | var endIndex int = int(math.Min(float64(offset+number), float64(len(workspaces)))) 20 | 21 | var finalWorkspaces models.Workspaces = workspaces[offset:endIndex] 22 | return finalWorkspaces, nil 23 | } 24 | 25 | func FetchWorkspace(workspaceId string) (models.Workspace, error) { 26 | logger.Log.Info("Fetching workspace from API for workspaceId: " + workspaceId) 27 | 28 | workspace, err := api.GetWorkspace(workspaceId) 29 | return workspace, err 30 | } 31 | 32 | func SearchWorkspace(searchString string) (models.Workspaces, error) { 33 | if searchString == "" { 34 | return models.Workspaces{}, errors.New("you passed an empty string") 35 | } 36 | 37 | workspaces, _ := api.GetWorkspaces() 38 | var filteredWorkspaces models.Workspaces 39 | 40 | for _, s := range workspaces { 41 | if strings.Contains(strings.ToLower(s.Name), strings.ToLower(searchString)) { 42 | filteredWorkspaces = append(filteredWorkspaces, s) 43 | } 44 | } 45 | 46 | return filteredWorkspaces, nil 47 | } 48 | -------------------------------------------------------------------------------- /cmd/check/check.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 NAME HERE 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package check 17 | 18 | import ( 19 | "github.com/harshithmullapudi/airbyte/logger" 20 | "github.com/spf13/cobra" 21 | ) 22 | 23 | // checkCmd represents the get command 24 | var CheckCmd = &cobra.Command{ 25 | Use: "check [sub]", 26 | Args: cobra.MinimumNArgs(1), 27 | Short: "Check connection to Source/Destination", 28 | Long: `Validate if the config and secrets are right for Source/Destination`, 29 | Run: func(cmd *cobra.Command, args []string) { 30 | logger.Notice("Kindly specify resource. Example (source, destination)") 31 | }, 32 | } 33 | 34 | func init() { 35 | // sub commands for get 36 | CheckCmd.AddCommand(SourceSubCmd) 37 | 38 | // Here you will define your flags and configuration settings. 39 | 40 | // Cobra supports Persistent Flags which will work for this command 41 | // and all subcommands, e.g.: 42 | // getCmd.PersistentFlags().String("foo", "", "A help for foo") 43 | 44 | // Cobra supports local flags which will only run when this command 45 | // is called directly, e.g.: 46 | // getCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 47 | } 48 | -------------------------------------------------------------------------------- /cmd/check/check_source.go: -------------------------------------------------------------------------------- 1 | package check 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/harshithmullapudi/airbyte/airbyte/api" 7 | "github.com/harshithmullapudi/airbyte/logger" 8 | "github.com/harshithmullapudi/airbyte/models" 9 | "github.com/spf13/cobra" 10 | ) 11 | 12 | var SourceSubCmd = &cobra.Command{ 13 | Use: "source [source Id]", 14 | Args: cobra.MinimumNArgs(1), 15 | Short: "Check source", 16 | Long: `Check whether the source is valid or not. Check this https://airbyte-public-api-docs.s3.us-east-2.amazonaws.com/rapidoc-api-docs.html#post-/v1/sources/check_connection`, 17 | Run: func(cmd *cobra.Command, args []string) { 18 | var sourceId string = args[0] 19 | var sourceCheck models.SourceCheckResponse 20 | sourceCheck, err := api.CheckSourceConnection(sourceId) 21 | 22 | if err != nil { 23 | cobra.CheckErr(err) 24 | } 25 | 26 | if sourceCheck.Status == "succeeded" { 27 | fmt.Println("\033[32m", "Source "+sourceId+" is valid") 28 | } else { 29 | logger.Error("This source " + sourceId + " is invalid - " + sourceCheck.Message) 30 | } 31 | }, 32 | } 33 | -------------------------------------------------------------------------------- /cmd/create/create.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 NAME HERE 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package create 17 | 18 | import ( 19 | "errors" 20 | "os" 21 | 22 | "github.com/harshithmullapudi/airbyte/logger" 23 | "github.com/spf13/cobra" 24 | ) 25 | 26 | // checkCmd represents the get command 27 | var CreateCmd = &cobra.Command{ 28 | Use: "create", 29 | Short: "Create Sources/Destinations/Connections", 30 | Long: `Create Sources/Destinations/Connections from a config folder. You need to have SOURCE_CONNECTION.yaml(sources), DESTINATION_CONNECTION.yaml(destinations), STANDARD_SYNC.yaml(connections) files. 31 | Note: This will neglect if the entity is already created. 32 | `, 33 | Run: func(cmd *cobra.Command, args []string) { 34 | configFolder, _ := cmd.Flags().GetString("folder") 35 | create, _ := cmd.Flags().GetBool("create") 36 | 37 | if configFolder == "" { 38 | logger.Error("provide config folder") 39 | cobra.CheckErr(errors.New("provide config folder")) 40 | } 41 | 42 | // Check if config folder exist 43 | _, err := os.Stat(configFolder) 44 | if os.IsNotExist(err) { 45 | logger.Error("No config folder found") 46 | cobra.CheckErr(err) 47 | } 48 | 49 | // Start with sources 50 | 51 | logger.Debug("Starting sources creation") 52 | CreateSources(configFolder, create) 53 | 54 | // Create destinations 55 | logger.Debug("Starting destinations creation") 56 | CreateDestinations(configFolder, create) 57 | 58 | // Create Connections 59 | logger.Debug("Starting connections creation") 60 | CreateConnections(configFolder, create) 61 | }, 62 | } 63 | 64 | func init() { 65 | CreateCmd.PersistentFlags().StringP("folder", "f", "", "Config folder") 66 | CreateCmd.PersistentFlags().BoolP("create", "c", false, "Setting this to false will only validate sources and doesn't create") 67 | } 68 | -------------------------------------------------------------------------------- /cmd/create/create_connection.go: -------------------------------------------------------------------------------- 1 | package create 2 | 3 | import ( 4 | "errors" 5 | "io/ioutil" 6 | "os" 7 | 8 | "github.com/harshithmullapudi/airbyte/airbyte/api" 9 | "github.com/harshithmullapudi/airbyte/logger" 10 | "github.com/harshithmullapudi/airbyte/models" 11 | "gopkg.in/yaml.v2" 12 | ) 13 | 14 | var CONNECTIONS_CONFIG_FILE = "STANDARD_SYNC.yaml" 15 | 16 | func CreateConnections(configFolderPath string, create bool) error { 17 | 18 | // Check if connections config file exists 19 | _, err := os.Stat(configFolderPath + "/" + CONNECTIONS_CONFIG_FILE) 20 | if os.IsNotExist(err) { 21 | logger.Warning("No config file found for connections. Skipping connections") 22 | return err 23 | } 24 | 25 | // Read config file 26 | var connections models.ConnectionsShort 27 | yamlFile, _ := ioutil.ReadFile(configFolderPath + "/" + CONNECTIONS_CONFIG_FILE) 28 | err = yaml.Unmarshal(yamlFile, &connections) 29 | if err != nil { 30 | logger.Errorf("Unmarshal: " + err.Error()) 31 | return err 32 | } 33 | 34 | if !create { 35 | ValidateAllConnections(connections) 36 | return nil 37 | } 38 | 39 | for _, connection := range connections { 40 | err = CreateConnection(connection) 41 | 42 | if err != nil { 43 | logger.Error(err) 44 | } 45 | 46 | } 47 | 48 | return nil 49 | } 50 | 51 | func ValidateAllConnections(connections models.ConnectionsShort) error { 52 | for _, connection := range connections { 53 | err := ValidateConnection(connection.SourceId, connection.DestinationId) 54 | 55 | if err != nil { 56 | logger.Error(err) 57 | } 58 | 59 | logger.Notice("Connection " + connection.SourceId + " - " + connection.DestinationId + " is valid") 60 | } 61 | 62 | return nil 63 | } 64 | 65 | func ValidateConnection(sourceId string, destinationId string) error { 66 | // Check if source exists 67 | _, err := api.GetSource(sourceId) 68 | 69 | if err != nil { 70 | return errors.New("Source not found for connection " + sourceId) 71 | } 72 | 73 | // Check if destination exists 74 | _, err = api.GetDestination(destinationId) 75 | 76 | if err != nil { 77 | return errors.New("Destination not found for connection " + destinationId) 78 | } 79 | 80 | return nil 81 | } 82 | 83 | func CreateConnection(connection models.ConnectionShort) error { 84 | 85 | // Validate i 86 | err := ValidateConnection(connection.SourceId, connection.DestinationId) 87 | 88 | if err != nil { 89 | return err 90 | } 91 | 92 | if connection.ConnectionId != "" { 93 | _, err := api.GetConnection(connection.ConnectionId) 94 | 95 | if err == nil { 96 | return errors.New("connection already exist") 97 | } 98 | } 99 | 100 | _, err = api.CreateConnection(connection) 101 | 102 | if err != nil { 103 | return errors.New("creation for connection failed " + err.Error()) 104 | } 105 | 106 | logger.Notice("Connection " + connection.SourceId + " - " + connection.DestinationId + " created successfully") 107 | 108 | return nil 109 | } 110 | -------------------------------------------------------------------------------- /cmd/create/create_destination.go: -------------------------------------------------------------------------------- 1 | package create 2 | 3 | import ( 4 | "errors" 5 | "io/ioutil" 6 | "os" 7 | 8 | "github.com/harshithmullapudi/airbyte/airbyte/api" 9 | "github.com/harshithmullapudi/airbyte/logger" 10 | "github.com/harshithmullapudi/airbyte/models" 11 | "gopkg.in/yaml.v2" 12 | ) 13 | 14 | var DESTINATIONS_CONFIG_FILE = "DESTINATION_CONNECTION.yaml" 15 | 16 | func CreateDestinations(configFolderPath string, create bool) error { 17 | 18 | // Check if destinations config file exists 19 | _, err := os.Stat(configFolderPath + "/" + DESTINATIONS_CONFIG_FILE) 20 | if os.IsNotExist(err) { 21 | logger.Warning("No config file found for destinations. Skipping destinations") 22 | return err 23 | } 24 | 25 | // Read config file 26 | var destinations models.Destinations 27 | yamlFile, _ := ioutil.ReadFile(configFolderPath + "/" + DESTINATIONS_CONFIG_FILE) 28 | err = yaml.Unmarshal(yamlFile, &destinations) 29 | if err != nil { 30 | logger.Errorf("Unmarshal: " + err.Error()) 31 | return err 32 | } 33 | 34 | if !create { 35 | ValidateAllDestinations(destinations) 36 | return nil 37 | } 38 | 39 | for _, destination := range destinations { 40 | err = CreateDestination(destination) 41 | 42 | if err != nil { 43 | logger.Error("Destination creation for " + destination.Name + " has failed. " + err.Error() + ". Skipping creation for this destination") 44 | } 45 | 46 | } 47 | 48 | return nil 49 | } 50 | 51 | func ValidateAllDestinations(destinations models.Destinations) error { 52 | for _, destination := range destinations { 53 | destinationCheckResponse, err := api.DestinationConnectionCheckSchedule(destination) 54 | 55 | if err != nil { 56 | logger.Error("Destination " + destination.Name + " has failed during validation with " + err.Error()) 57 | continue 58 | } 59 | 60 | if destinationCheckResponse.Status != "succeeded" { 61 | logger.Error("Destination " + destination.Name + " has failed during validation with " + destinationCheckResponse.Message) 62 | continue 63 | } 64 | 65 | logger.Notice("Destination " + destination.Name + " has passed validation") 66 | } 67 | 68 | return nil 69 | } 70 | 71 | func CreateDestination(destination models.Destination) error { 72 | 73 | // Validate i 74 | destinationCheckResponse, err := api.DestinationConnectionCheckSchedule(destination) 75 | 76 | if err != nil { 77 | return err 78 | } 79 | 80 | if destinationCheckResponse.Status != "succeeded" { 81 | return errors.New("validation for destination failed") 82 | } 83 | 84 | if destination.DestinationId != "" { 85 | _, err := api.GetDestination(destination.DestinationId) 86 | 87 | if err == nil { 88 | return errors.New("destination already exist") 89 | } 90 | } 91 | 92 | _, err = api.CreateDestination(destination) 93 | 94 | if err != nil { 95 | return errors.New("creation for destination failed") 96 | } 97 | 98 | logger.Notice("Destination " + destination.Name + " created successfully") 99 | 100 | return nil 101 | } 102 | -------------------------------------------------------------------------------- /cmd/create/create_sources.go: -------------------------------------------------------------------------------- 1 | package create 2 | 3 | import ( 4 | "errors" 5 | "io/ioutil" 6 | "os" 7 | 8 | "github.com/harshithmullapudi/airbyte/airbyte/api" 9 | "github.com/harshithmullapudi/airbyte/logger" 10 | "github.com/harshithmullapudi/airbyte/models" 11 | "gopkg.in/yaml.v2" 12 | ) 13 | 14 | var SOURCES_CONFIG_FILE = "SOURCE_CONNECTION.yaml" 15 | 16 | func CreateSources(configFolderPath string, create bool) error { 17 | 18 | // Check if sources config file exists 19 | _, err := os.Stat(configFolderPath + "/" + SOURCES_CONFIG_FILE) 20 | if os.IsNotExist(err) { 21 | logger.Warning("No config file found for sources. Skipping sources") 22 | return err 23 | } 24 | 25 | // Read config file 26 | var sources models.Sources 27 | yamlFile, _ := ioutil.ReadFile(configFolderPath + "/" + SOURCES_CONFIG_FILE) 28 | err = yaml.Unmarshal(yamlFile, &sources) 29 | if err != nil { 30 | logger.Errorf("Unmarshal: " + err.Error()) 31 | return err 32 | } 33 | 34 | if !create { 35 | ValidateAllSources(sources) 36 | return nil 37 | } 38 | 39 | for _, source := range sources { 40 | err = CreateSource(source) 41 | 42 | if err != nil { 43 | logger.Error("Source creation for " + source.Name + " has failed. " + err.Error() + ". Skipping creation for this source") 44 | } 45 | 46 | } 47 | 48 | return nil 49 | } 50 | 51 | func ValidateAllSources(sources models.Sources) error { 52 | for _, source := range sources { 53 | sourceCheckResponse, err := api.SourceConnectionCheckSchedule(source) 54 | 55 | if err != nil { 56 | logger.Error("Source " + source.Name + " has failed during validation with " + err.Error()) 57 | continue 58 | } 59 | 60 | if sourceCheckResponse.Status != "succeeded" { 61 | logger.Error("Source " + source.Name + " has failed during validation with " + sourceCheckResponse.Message) 62 | continue 63 | } 64 | 65 | logger.Notice("Source " + source.Name + " has passed validation") 66 | } 67 | 68 | return nil 69 | } 70 | 71 | func CreateSource(source models.Source) error { 72 | 73 | // Validate i 74 | sourceCheckResponse, err := api.SourceConnectionCheckSchedule(source) 75 | 76 | if err != nil { 77 | return err 78 | } 79 | 80 | if sourceCheckResponse.Status != "succeeded" { 81 | return errors.New("validation for source failed") 82 | } 83 | 84 | if source.SourceId != "" { 85 | _, err := api.GetSource(source.SourceId) 86 | 87 | if err == nil { 88 | return errors.New("source already exist") 89 | } 90 | } 91 | 92 | _, err = api.CreateSource(source) 93 | 94 | if err != nil { 95 | return errors.New("creation for source failed") 96 | } 97 | 98 | logger.Notice("Source " + source.Name + " created successfully") 99 | 100 | return nil 101 | } 102 | -------------------------------------------------------------------------------- /cmd/export/export.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 NAME HERE 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package export 17 | 18 | import ( 19 | "errors" 20 | "os" 21 | 22 | "github.com/harshithmullapudi/airbyte/common" 23 | "github.com/harshithmullapudi/airbyte/logger" 24 | "github.com/spf13/cobra" 25 | ) 26 | 27 | // checkCmd represents the get command 28 | var ExportCmd = &cobra.Command{ 29 | Use: "export", 30 | Short: "Export Sources/Destinations/Connections", 31 | Long: `Export Sources/Destinations/Connections`, 32 | Run: func(cmd *cobra.Command, args []string) { 33 | target, _ := cmd.Flags().GetString("target") 34 | 35 | if target == "" { 36 | logger.Error("No target specified") 37 | cobra.CheckErr(errors.New("no target specified")) 38 | } 39 | 40 | logger.Info("Downloading the config...") 41 | 42 | err := common.DownloadFile() 43 | 44 | if err != nil { 45 | logger.Error(err) 46 | } 47 | 48 | err = common.Untar() 49 | 50 | if err != nil { 51 | logger.Error(err) 52 | } 53 | 54 | logger.Info("Downloaded and extracted the config.") 55 | 56 | if err := os.MkdirAll(target, 0755); err != nil { 57 | cobra.CheckErr(err) 58 | } 59 | 60 | err = common.CopyConfigToTarget(target) 61 | 62 | if err != nil { 63 | logger.Error(err) 64 | cobra.CheckErr(err) 65 | } 66 | 67 | logger.Notice("Exported successfully") 68 | 69 | err = common.CleanUp() 70 | if err != nil { 71 | logger.Error(err) 72 | cobra.CheckErr(err) 73 | } 74 | }, 75 | } 76 | 77 | func init() { 78 | ExportCmd.PersistentFlags().StringP("target", "t", "", "Target folder to export") 79 | } 80 | -------------------------------------------------------------------------------- /cmd/get/get.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 NAME HERE 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package get 17 | 18 | import ( 19 | "github.com/harshithmullapudi/airbyte/logger" 20 | "github.com/spf13/cobra" 21 | ) 22 | 23 | // getCmd represents the get command 24 | var GetCmd = &cobra.Command{ 25 | Use: "get [sub]", 26 | Args: cobra.MinimumNArgs(1), 27 | Short: "Get configuration of Sources/Destinations/Connections", 28 | Long: `Get configuration of Sources/Destinations/Connections`, 29 | Run: func(cmd *cobra.Command, args []string) { 30 | logger.Notice("Kindly specify resource. Example (workspaces, sources, connections, destinations, workspace, source, destination, connection)") 31 | }, 32 | } 33 | 34 | func init() { 35 | // sub commands for get 36 | GetCmd.AddCommand(WorkspaceSubCmd) 37 | GetCmd.AddCommand(WorkspacesSubCmd) 38 | GetCmd.AddCommand(SourcesSubCmd) 39 | GetCmd.AddCommand(SourceDefinitionsSubCmd) 40 | GetCmd.AddCommand(DestinationsSubCmd) 41 | GetCmd.AddCommand(ConnectionsSubCmd) 42 | GetCmd.AddCommand(SourceSubCmd) 43 | GetCmd.AddCommand(ConnectionSubCmd) 44 | GetCmd.AddCommand(JobsSubCmd) 45 | GetCmd.AddCommand(JobSubCmd) 46 | GetCmd.AddCommand(DestinationSubCmd) 47 | 48 | // Here you will define your flags and configuration settings. 49 | 50 | // Cobra supports Persistent Flags which will work for this command 51 | // and all subcommands, e.g.: 52 | // getCmd.PersistentFlags().String("foo", "", "A help for foo") 53 | 54 | // Cobra supports local flags which will only run when this command 55 | // is called directly, e.g.: 56 | // getCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 57 | } 58 | -------------------------------------------------------------------------------- /cmd/get/get_connections.go: -------------------------------------------------------------------------------- 1 | package get 2 | 3 | import ( 4 | "github.com/harshithmullapudi/airbyte/airbyte" 5 | "github.com/harshithmullapudi/airbyte/airbyte/api" 6 | "github.com/harshithmullapudi/airbyte/models" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | var ConnectionsSubCmd = &cobra.Command{ 11 | Use: "connections", 12 | Short: "Returns all connections with pagination", 13 | Long: `Returns all connections with pagination. You can use page(p) and offset(o) to fetch connections respectively. Check this https://airbyte-public-api-docs.s3.us-east-2.amazonaws.com/rapidoc-api-docs.html#post-/v1/connections/list`, 14 | Run: func(cmd *cobra.Command, args []string) { 15 | number, _ := cmd.Flags().GetInt("number") 16 | offset, _ := cmd.Flags().GetInt("offset") 17 | format, _ := cmd.Flags().GetString("format") 18 | status, _ := cmd.Flags().GetString("status") 19 | 20 | var connections models.Connections 21 | connections, err := airbyte.PaginateConnections(offset, number, status) 22 | 23 | if err != nil { 24 | cobra.CheckErr(err) 25 | } 26 | 27 | if format == "table" { 28 | airbyte.PrintConnectionsTable(connections) 29 | } else { 30 | airbyte.PrintConnections(connections) 31 | } 32 | }, 33 | } 34 | 35 | var ConnectionSubCmd = &cobra.Command{ 36 | Use: "connection [connection Id]", 37 | Args: cobra.MinimumNArgs(1), 38 | Short: "Get a connection", 39 | Long: `Get a connection in table/json format. Check this https://airbyte-public-api-docs.s3.us-east-2.amazonaws.com/rapidoc-api-docs.html#post-/v1/connections/get`, 40 | Run: func(cmd *cobra.Command, args []string) { 41 | var connectionId string = args[0] 42 | format, _ := cmd.Flags().GetString("format") 43 | 44 | connection, err := api.GetConnection(connectionId) 45 | 46 | if err != nil { 47 | cobra.CheckErr(err) 48 | } 49 | 50 | if format == "table" { 51 | airbyte.PrintConnectionTable(connection) 52 | } else { 53 | airbyte.PrintConnection(connection) 54 | } 55 | 56 | }, 57 | } 58 | 59 | func init() { 60 | ConnectionsSubCmd.PersistentFlags().IntP("number", "n", 10, "Number of sources to fetch") 61 | ConnectionsSubCmd.PersistentFlags().IntP("offset", "o", 0, "Offset") 62 | ConnectionsSubCmd.PersistentFlags().StringP("status", "s", "", "Print format") 63 | ConnectionsSubCmd.PersistentFlags().StringP("format", "f", "table", "Print format") 64 | 65 | ConnectionSubCmd.PersistentFlags().StringP("format", "f", "table", "Print format") 66 | } 67 | -------------------------------------------------------------------------------- /cmd/get/get_destinations.go: -------------------------------------------------------------------------------- 1 | package get 2 | 3 | import ( 4 | "github.com/harshithmullapudi/airbyte/airbyte" 5 | "github.com/harshithmullapudi/airbyte/models" 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | var DestinationsSubCmd = &cobra.Command{ 10 | Use: "destinations", 11 | Short: "Return all destinations with pagination", 12 | Long: `Return all destinations with pagination. You can use page(p) and offset(o) to fetch destinations respectively. Check this https://airbyte-public-api-docs.s3.us-east-2.amazonaws.com/rapidoc-api-docs.html#post-/v1/destinations/list`, 13 | Run: func(cmd *cobra.Command, args []string) { 14 | number, _ := cmd.Flags().GetInt("number") 15 | offset, _ := cmd.Flags().GetInt("offset") 16 | format, _ := cmd.Flags().GetString("format") 17 | var destinations models.Destinations 18 | destinations, err := airbyte.PaginateDestinations(offset, number) 19 | 20 | if err != nil { 21 | cobra.CheckErr(err) 22 | } 23 | 24 | if format == "table" { 25 | airbyte.PrintDestinationsTable(destinations) 26 | } else { 27 | airbyte.PrintDestinations(destinations) 28 | } 29 | }, 30 | } 31 | 32 | var DestinationSubCmd = &cobra.Command{ 33 | Use: "destination [destination Id]", 34 | Args: cobra.MinimumNArgs(1), 35 | Short: "Get configured destination", 36 | Long: `Get configured destination in table/json format. Check this https://airbyte-public-api-docs.s3.us-east-2.amazonaws.com/rapidoc-api-docs.html#post-/v1/destinations/get`, 37 | Run: func(cmd *cobra.Command, args []string) { 38 | var destinationId string = args[0] 39 | format, _ := cmd.Flags().GetString("format") 40 | destination, err := airbyte.FetchDestination(destinationId) 41 | 42 | if err != nil { 43 | cobra.CheckErr(err) 44 | } 45 | 46 | if format == "table" { 47 | airbyte.PrintDestinationTable(destination) 48 | } else { 49 | airbyte.PrintDestination(destination) 50 | } 51 | }, 52 | } 53 | 54 | func init() { 55 | DestinationsSubCmd.PersistentFlags().IntP("number", "n", 10, "Number of sources to fetch") 56 | DestinationsSubCmd.PersistentFlags().IntP("offset", "o", 0, "Offset") 57 | DestinationsSubCmd.PersistentFlags().StringP("format", "f", "table", "Offset") 58 | 59 | DestinationSubCmd.PersistentFlags().StringP("format", "f", "table", "Offset") 60 | } 61 | -------------------------------------------------------------------------------- /cmd/get/get_jobs.go: -------------------------------------------------------------------------------- 1 | package get 2 | 3 | import ( 4 | "strconv" 5 | 6 | "github.com/harshithmullapudi/airbyte/airbyte" 7 | "github.com/harshithmullapudi/airbyte/models" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | var JobsSubCmd = &cobra.Command{ 12 | Use: "jobs [configId] [configType]", 13 | Short: "Returns recent jobs for a connection. Jobs are returned in descending order by createdAt", 14 | Long: `Fetch all jobs. Check https://airbyte-public-api-docs.s3.us-east-2.amazonaws.com/rapidoc-api-docs.html#post-/v1/jobs/list`, 15 | Run: func(cmd *cobra.Command, args []string) { 16 | var configId string = args[0] 17 | 18 | format, _ := cmd.Flags().GetString("format") 19 | configType, _ := cmd.Flags().GetString("type") 20 | 21 | var jobs models.Jobs 22 | jobs, err := airbyte.PaginateJobs(configId, configType) 23 | 24 | if err != nil { 25 | cobra.CheckErr(err) 26 | } 27 | 28 | if format == "table" { 29 | airbyte.PrintJobsTable(jobs) 30 | } else { 31 | } 32 | }, 33 | } 34 | 35 | var JobSubCmd = &cobra.Command{ 36 | Use: "job [jobId]", 37 | Short: "Get information about a job", 38 | Long: `Get information about a job. Check https://airbyte-public-api-docs.s3.us-east-2.amazonaws.com/rapidoc-api-docs.html#post-/v1/jobs/get`, 39 | Run: func(cmd *cobra.Command, args []string) { 40 | var jobId int 41 | jobId, _ = strconv.Atoi(args[0]) 42 | 43 | format, _ := cmd.Flags().GetString("format") 44 | 45 | job, err := airbyte.FetchJob(jobId) 46 | 47 | if err != nil { 48 | cobra.CheckErr(err) 49 | } 50 | 51 | if format == "table" { 52 | airbyte.PrintJobTable(job) 53 | } else { 54 | } 55 | }, 56 | } 57 | 58 | func init() { 59 | JobsSubCmd.PersistentFlags().StringP("format", "f", "table", "Print format") 60 | JobsSubCmd.PersistentFlags().StringP("type", "t", "sync", "Config Type") 61 | 62 | JobSubCmd.PersistentFlags().StringP("format", "f", "table", "Print format") 63 | } 64 | -------------------------------------------------------------------------------- /cmd/get/get_source_definitions.go: -------------------------------------------------------------------------------- 1 | package get 2 | 3 | import ( 4 | "github.com/harshithmullapudi/airbyte/airbyte" 5 | "github.com/harshithmullapudi/airbyte/airbyte/api" 6 | "github.com/harshithmullapudi/airbyte/models" 7 | "github.com/spf13/cobra" 8 | ) 9 | 10 | var SourceDefinitionsSubCmd = &cobra.Command{ 11 | Use: "source_definitions", 12 | Short: "Get source definitions", 13 | Long: `Fetch all source definitions.`, 14 | Run: func(cmd *cobra.Command, args []string) { 15 | format, _ := cmd.Flags().GetString("format") 16 | var source_definitions models.SourceDefinitions 17 | source_definitions, err := api.GetSourceDefinitions() 18 | 19 | if err != nil { 20 | cobra.CheckErr(err) 21 | } 22 | 23 | if format == "table" { 24 | airbyte.PrintSourceDefinitionsTable(source_definitions) 25 | } else { 26 | } 27 | }, 28 | } 29 | 30 | func init() { 31 | 32 | SourceDefinitionsSubCmd.PersistentFlags().StringP("format", "f", "table", "Print format") 33 | } 34 | -------------------------------------------------------------------------------- /cmd/get/get_sources.go: -------------------------------------------------------------------------------- 1 | package get 2 | 3 | import ( 4 | "github.com/harshithmullapudi/airbyte/airbyte" 5 | "github.com/harshithmullapudi/airbyte/models" 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | var SourcesSubCmd = &cobra.Command{ 10 | Use: "sources", 11 | Short: "Return all sources", 12 | Long: `Return all sources with pagination. You can use page(p) and offset(o) to fetch sources respectively. Check this https://airbyte-public-api-docs.s3.us-east-2.amazonaws.com/rapidoc-api-docs.html#post-/v1/sources/list`, 13 | Run: func(cmd *cobra.Command, args []string) { 14 | number, _ := cmd.Flags().GetInt("number") 15 | offset, _ := cmd.Flags().GetInt("offset") 16 | format, _ := cmd.Flags().GetString("format") 17 | var sources models.Sources 18 | sources, err := airbyte.PaginateSources(offset, number) 19 | 20 | if err != nil { 21 | cobra.CheckErr(err) 22 | } 23 | 24 | if format == "table" { 25 | airbyte.PrintSourcesTable(sources) 26 | } else { 27 | airbyte.PrintSources(sources) 28 | } 29 | }, 30 | } 31 | 32 | var SourceSubCmd = &cobra.Command{ 33 | Use: "source [source Id]", 34 | Args: cobra.MinimumNArgs(1), 35 | Short: "Get a connection", 36 | Long: `Get a connection in table/json format. Check this https://airbyte-public-api-docs.s3.us-east-2.amazonaws.com/rapidoc-api-docs.html#post-/v1/sources/get`, 37 | Run: func(cmd *cobra.Command, args []string) { 38 | var sourceId string = args[0] 39 | format, _ := cmd.Flags().GetString("format") 40 | source, err := airbyte.FetchSource(sourceId) 41 | 42 | if err != nil { 43 | cobra.CheckErr(err) 44 | } 45 | 46 | if format == "table" { 47 | airbyte.PrintSourceTable(source) 48 | } else { 49 | airbyte.PrintSource(source) 50 | } 51 | }, 52 | } 53 | 54 | func init() { 55 | SourcesSubCmd.PersistentFlags().IntP("number", "n", 10, "Number of sources to fetch") 56 | SourcesSubCmd.PersistentFlags().IntP("offset", "o", 0, "Offset") 57 | SourcesSubCmd.PersistentFlags().StringP("format", "f", "table", "Print format") 58 | 59 | SourceSubCmd.PersistentFlags().StringP("format", "f", "json", "Print format") 60 | } 61 | -------------------------------------------------------------------------------- /cmd/get/get_workspaces.go: -------------------------------------------------------------------------------- 1 | package get 2 | 3 | import ( 4 | "github.com/harshithmullapudi/airbyte/airbyte" 5 | "github.com/harshithmullapudi/airbyte/models" 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | var WorkspacesSubCmd = &cobra.Command{ 10 | Use: "workspaces", 11 | Short: "Return all workspaces", 12 | Long: `Return all workspaces with pagination. You can use page(p) and offset(o) to fetch workspaces respectively. Check this https://airbyte-public-api-docs.s3.us-east-2.amazonaws.com/rapidoc-api-docs.html#post-/v1/workspaces/list`, 13 | Run: func(cmd *cobra.Command, args []string) { 14 | number, _ := cmd.Flags().GetInt("number") 15 | offset, _ := cmd.Flags().GetInt("offset") 16 | format, _ := cmd.Flags().GetString("format") 17 | var workspaces models.Workspaces 18 | workspaces, err := airbyte.PaginateWorkspaces(offset, number) 19 | 20 | if err != nil { 21 | cobra.CheckErr(err) 22 | } 23 | 24 | if format == "table" { 25 | airbyte.PrintWorkspacesTable(workspaces) 26 | } else { 27 | airbyte.PrintWorkspaces(workspaces) 28 | } 29 | }, 30 | } 31 | 32 | var WorkspaceSubCmd = &cobra.Command{ 33 | Use: "workspace [workspace Id]", 34 | Args: cobra.MinimumNArgs(1), 35 | Short: "Get a workspace", 36 | Long: `Get a workspace in table/json format. Check this https://airbyte-public-api-docs.s3.us-east-2.amazonaws.com/rapidoc-api-docs.html#post-/v1/workspaces/get`, 37 | Run: func(cmd *cobra.Command, args []string) { 38 | var workspaceId string = args[0] 39 | format, _ := cmd.Flags().GetString("format") 40 | workspace, err := airbyte.FetchWorkspace(workspaceId) 41 | 42 | if err != nil { 43 | cobra.CheckErr(err) 44 | } 45 | 46 | if format == "table" { 47 | airbyte.PrintWorkspaceTable(workspace) 48 | } else { 49 | airbyte.PrintWorkspace(workspace) 50 | } 51 | }, 52 | } 53 | 54 | func init() { 55 | WorkspacesSubCmd.PersistentFlags().IntP("number", "n", 10, "Number of sources to fetch") 56 | WorkspacesSubCmd.PersistentFlags().IntP("offset", "o", 0, "Offset") 57 | WorkspacesSubCmd.PersistentFlags().StringP("format", "f", "table", "Print format") 58 | 59 | WorkspaceSubCmd.PersistentFlags().StringP("format", "f", "json", "Print format") 60 | } 61 | -------------------------------------------------------------------------------- /cmd/logs.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "strconv" 7 | 8 | "github.com/harshithmullapudi/airbyte/airbyte/api" 9 | "github.com/spf13/cobra" 10 | ) 11 | 12 | var logsCmd = &cobra.Command{ 13 | Use: "logs [jobId]", 14 | Short: "Fetch logs for a job", 15 | Long: `Fetch logs for a job 16 | `, 17 | Run: func(cmd *cobra.Command, args []string) { 18 | 19 | if len(args) == 0 { 20 | cobra.CheckErr(errors.New("Missing job ID")) 21 | } 22 | 23 | var jobId int 24 | jobId, _ = strconv.Atoi(args[0]) 25 | 26 | attemptNumber, _ := cmd.Flags().GetInt("attempt") 27 | job, err := api.GetJob(jobId) 28 | if err != nil { 29 | cobra.CheckErr(err) 30 | } 31 | 32 | for index, attempt := range job.Attempts { 33 | if (index + 1) == attemptNumber { 34 | for _, logs := range attempt.Logs.LogLines { 35 | fmt.Println(logs) 36 | } 37 | } 38 | } 39 | }, 40 | } 41 | 42 | func init() { 43 | rootCmd.AddCommand(logsCmd) 44 | logsCmd.PersistentFlags().IntP("attempt", "a", 1, "Attempt number") 45 | } 46 | -------------------------------------------------------------------------------- /cmd/root.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 NAME HERE 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package cmd 17 | 18 | import ( 19 | "fmt" 20 | "os" 21 | 22 | "github.com/harshithmullapudi/airbyte/cmd/check" 23 | "github.com/harshithmullapudi/airbyte/cmd/create" 24 | "github.com/harshithmullapudi/airbyte/cmd/export" 25 | "github.com/harshithmullapudi/airbyte/cmd/get" 26 | "github.com/harshithmullapudi/airbyte/cmd/search" 27 | "github.com/harshithmullapudi/airbyte/logger" 28 | 29 | "github.com/spf13/cobra" 30 | 31 | "github.com/spf13/viper" 32 | ) 33 | 34 | var cfgFile string 35 | 36 | // rootCmd represents the base command when called without any subcommands 37 | var rootCmd = &cobra.Command{ 38 | Use: "airbyte", 39 | Short: "CLI tool for Airbyte", 40 | Long: `CLI tool for Airbyte`, 41 | } 42 | 43 | // Execute adds all child commands to the root command and sets flags appropriately. 44 | // This is called by main.main(). It only needs to happen once to the rootCmd. 45 | func Execute() { 46 | rootCmd.Execute() 47 | } 48 | 49 | func init() { 50 | cobra.OnInitialize(initConfig) 51 | 52 | // Here you will define your flags and configuration settings. 53 | // Cobra supports persistent flags, which, if defined here, 54 | // will be global for your application. 55 | 56 | rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default searhes for file $HOME/.airbyte.yaml)") 57 | 58 | // Cobra also supports local flags, which will only run 59 | // when this action is called directly. 60 | rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 61 | 62 | // Add sub commands 63 | rootCmd.AddCommand(get.GetCmd) 64 | rootCmd.AddCommand(search.SearchCmd) 65 | rootCmd.AddCommand(check.CheckCmd) 66 | rootCmd.AddCommand(export.ExportCmd) 67 | rootCmd.AddCommand(create.CreateCmd) 68 | 69 | } 70 | 71 | // initConfig reads in config file and ENV variables if set. 72 | func initConfig() { 73 | dirname, err := os.UserHomeDir() 74 | 75 | if err != nil { 76 | cobra.CheckErr(err) 77 | } 78 | 79 | _, err = os.Stat(dirname + "/.airbyte.yaml") 80 | 81 | if os.IsNotExist(err) { 82 | f, e := os.Create(dirname + "/.airbyte.yaml") 83 | if e != nil { 84 | cobra.CheckErr(err) 85 | } 86 | defer f.Close() 87 | } 88 | 89 | if err := os.Mkdir(dirname+"/.airbyte", 0755); !os.IsExist(err) { 90 | logger.Info("Create .airbyte folder") 91 | } 92 | 93 | if cfgFile != "" { 94 | // Use config file from the flag. 95 | viper.SetConfigFile(cfgFile) 96 | } else { 97 | 98 | // Search config in home directory with name ".airbyte" (without extension). 99 | viper.AddConfigPath(dirname) 100 | viper.SetConfigName(".airbyte") 101 | } 102 | 103 | viper.AutomaticEnv() // read in environment variables that match 104 | 105 | // If a config file is found, read it in. 106 | if err := viper.ReadInConfig(); err == nil { 107 | fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /cmd/search/search.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 NAME HERE 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package search 17 | 18 | import ( 19 | "github.com/harshithmullapudi/airbyte/logger" 20 | "github.com/spf13/cobra" 21 | ) 22 | 23 | // searchCmd represents the search command 24 | var SearchCmd = &cobra.Command{ 25 | Use: "search", 26 | Args: cobra.MinimumNArgs(1), 27 | Short: "Search in Sources/Connections", 28 | Long: ``, 29 | Run: func(cmd *cobra.Command, args []string) { 30 | logger.Notice("Kindly specify resource. Example (sources, connections)") 31 | }, 32 | } 33 | 34 | func init() { 35 | 36 | // sub commands for get 37 | SearchCmd.AddCommand(SourcesSearchCmd) 38 | SearchCmd.AddCommand(ConnectionsSearchCmd) 39 | // Here you will define your flags and configuration settings. 40 | 41 | // Cobra supports Persistent Flags which will work for this command 42 | // and all subcommands, e.g.: 43 | // searchCmd.PersistentFlags().String("foo", "", "A help for foo") 44 | 45 | // Cobra supports local flags which will only run when this command 46 | // is called directly, e.g.: 47 | // searchCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 48 | } 49 | -------------------------------------------------------------------------------- /cmd/search/search_connections.go: -------------------------------------------------------------------------------- 1 | package search 2 | 3 | import ( 4 | "github.com/harshithmullapudi/airbyte/airbyte" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | var ConnectionsSearchCmd = &cobra.Command{ 9 | Use: "connections", 10 | Args: cobra.MinimumNArgs(1), 11 | Short: "Search connections", 12 | Long: `Search all connections.`, 13 | Run: func(cmd *cobra.Command, args []string) { 14 | var searchString string = args[0] 15 | 16 | connections, err := airbyte.SearchConnection(searchString) 17 | 18 | if err != nil { 19 | cobra.CheckErr(err) 20 | return 21 | } 22 | 23 | airbyte.PrintConnectionsTable(connections) 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /cmd/search/search_sources.go: -------------------------------------------------------------------------------- 1 | package search 2 | 3 | import ( 4 | "github.com/harshithmullapudi/airbyte/airbyte" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | var SourcesSearchCmd = &cobra.Command{ 9 | Use: "sources", 10 | Args: cobra.MinimumNArgs(1), 11 | Short: "Search sources", 12 | Long: `Search all sources.`, 13 | Run: func(cmd *cobra.Command, args []string) { 14 | var searchString string = args[0] 15 | 16 | sources, err := airbyte.SearchSource(searchString) 17 | 18 | if err != nil { 19 | cobra.CheckErr(err) 20 | return 21 | } 22 | 23 | airbyte.PrintSourcesTable(sources) 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /cmd/set.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 NAME HERE 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package cmd 17 | 18 | import ( 19 | "bufio" 20 | "fmt" 21 | "os" 22 | "strings" 23 | 24 | "github.com/harshithmullapudi/airbyte/airbyte/api" 25 | "github.com/harshithmullapudi/airbyte/common" 26 | "github.com/harshithmullapudi/airbyte/logger" 27 | "github.com/harshithmullapudi/airbyte/models" 28 | "github.com/spf13/cobra" 29 | "github.com/spf13/viper" 30 | ) 31 | 32 | // setCmd represents the set command 33 | var setCmd = &cobra.Command{ 34 | Use: "set-config", 35 | Short: "Set your airbyte url and workspaceID", 36 | Long: `You need to set airbyte url and workspaceID`, 37 | Run: func(cmd *cobra.Command, args []string) { 38 | fmt.Print("Enter airbyte URL here: ") 39 | URL := bufio.NewScanner(os.Stdin) 40 | URL.Scan() 41 | _, error := common.CheckForURL(URL.Text()) 42 | 43 | if error != nil { 44 | cobra.CheckErr(error) 45 | return 46 | } 47 | 48 | // Remove trailing slash if any 49 | api_url := strings.TrimSuffix(URL.Text(), "/") 50 | 51 | viper.Set("airbyte_url", api_url) 52 | 53 | fmt.Print("Enter current workspace (leave blank for default): ") 54 | 55 | workspaceId := bufio.NewScanner(os.Stdin) 56 | workspaceId.Scan() 57 | 58 | var workspace models.Workspace 59 | workspace, error = api.GetWorkspace(workspaceId.Text()) 60 | 61 | if error != nil { 62 | cobra.CheckErr(error) 63 | return 64 | } 65 | 66 | viper.Set("workspace_id", workspaceId.Text()) 67 | // Finally write config to config file 68 | viper.WriteConfig() 69 | 70 | logger.Notice("We found workspace with name: " + workspace.Name + " and email: " + workspace.Email) 71 | }, 72 | } 73 | 74 | func init() { 75 | rootCmd.AddCommand(setCmd) 76 | 77 | // Here you will define your flags and configuration settings. 78 | 79 | // Cobra supports Persistent Flags which will work for this command 80 | // and all subcommands, e.g.: 81 | // setCmd.PersistentFlags().String("foo", "", "A help for foo") 82 | 83 | // Cobra supports local flags which will only run when this command 84 | // is called directly, e.g.: 85 | // setCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 86 | } 87 | -------------------------------------------------------------------------------- /common/api_utils.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "errors" 7 | "io/ioutil" 8 | "net/http" 9 | 10 | "github.com/harshithmullapudi/airbyte/models" 11 | jsoniter "github.com/json-iterator/go" 12 | "github.com/spf13/viper" 13 | ) 14 | 15 | func GetFullApiURL(path string) string { 16 | airbyte_url := viper.GetString("airbyte_url") 17 | return airbyte_url + path 18 | } 19 | 20 | func ApiCall(API_URL string, jsonBody map[string]string) ([]byte, error) { 21 | 22 | var body []byte 23 | 24 | if len(jsonBody) != 0 { 25 | body, _ = json.Marshal(jsonBody) 26 | 27 | } else { 28 | body, _ = json.Marshal(map[string]string{}) 29 | } 30 | 31 | requestBody := bytes.NewBuffer(body) 32 | 33 | //Leverage Go's HTTP Post function to make request 34 | resp, err := http.Post(API_URL, "application/json", requestBody) 35 | 36 | //Handle Error 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | if resp.StatusCode != 200 { 42 | //Read the response body 43 | errBody, _ := ioutil.ReadAll(resp.Body) 44 | var errorResponse models.ErrorResponse 45 | json.Unmarshal(errBody, &errorResponse) 46 | return nil, errors.New(errorResponse.Message) 47 | } 48 | 49 | defer resp.Body.Close() 50 | 51 | //Read the response body 52 | respBody, err := ioutil.ReadAll(resp.Body) 53 | 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | return respBody, nil 59 | } 60 | 61 | func ApiCallInterface(API_URL string, jsonBody map[interface{}]interface{}) ([]byte, error) { 62 | 63 | var body []byte 64 | var err error 65 | 66 | var json = jsoniter.ConfigCompatibleWithStandardLibrary 67 | 68 | if len(jsonBody) != 0 { 69 | body, _ = json.Marshal(jsonBody) 70 | } else { 71 | body, _ = json.Marshal(map[string]string{}) 72 | } 73 | 74 | requestBody := bytes.NewBuffer(body) 75 | 76 | //Leverage Go's HTTP Post function to make request 77 | resp, err := http.Post(API_URL, "application/json", requestBody) 78 | 79 | //Handle Error 80 | if err != nil { 81 | return nil, err 82 | } 83 | 84 | if resp.StatusCode != 200 { 85 | //Read the response body 86 | errBody, _ := ioutil.ReadAll(resp.Body) 87 | var errorResponse models.ErrorResponse 88 | json.Unmarshal(errBody, &errorResponse) 89 | return nil, errors.New(errorResponse.Message) 90 | } 91 | 92 | defer resp.Body.Close() 93 | 94 | //Read the response body 95 | respBody, err := ioutil.ReadAll(resp.Body) 96 | if err != nil { 97 | return nil, err 98 | } 99 | 100 | return respBody, nil 101 | } 102 | -------------------------------------------------------------------------------- /common/tar_utils.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "archive/tar" 5 | "bufio" 6 | "bytes" 7 | "compress/gzip" 8 | "context" 9 | "encoding/json" 10 | "fmt" 11 | "io" 12 | "net/http" 13 | "os" 14 | "path/filepath" 15 | "strings" 16 | "time" 17 | ) 18 | 19 | var FILE_NAME = "archive.tar" 20 | 21 | // Download the config from the airbyte API 22 | func DownloadFile() (err error) { 23 | var DOWNLOAD_CONFIG = "/api/v1/deployment/export" 24 | 25 | url := GetFullApiURL(DOWNLOAD_CONFIG) 26 | dirname, err := os.UserHomeDir() 27 | 28 | // Create the file 29 | out, err := os.Create(dirname + "/.airbyte/" + FILE_NAME) 30 | if err != nil { 31 | return err 32 | } 33 | defer out.Close() 34 | 35 | // Post the data 36 | body, _ := json.Marshal(map[string]string{}) 37 | requestBody := bytes.NewBuffer(body) 38 | 39 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) 40 | defer cancel() 41 | 42 | req, _ := http.NewRequest("POST", url, requestBody) 43 | 44 | resp, err := http.DefaultClient.Do(req.WithContext(ctx)) 45 | if err != nil { 46 | return err 47 | } 48 | defer resp.Body.Close() 49 | 50 | // Check server response 51 | if resp.StatusCode != http.StatusOK { 52 | return fmt.Errorf("bad status: %s", resp.Status) 53 | } 54 | 55 | // Writer the body to file 56 | _, err = io.Copy(out, resp.Body) 57 | if err != nil { 58 | return err 59 | } 60 | 61 | return nil 62 | } 63 | 64 | // Untar takes a destination path and a reader; a tar reader loops over the tarfile 65 | // creating the file structure at 'dst' along the way, and writing any files 66 | func Untar() error { 67 | dirname, _ := os.UserHomeDir() 68 | 69 | dst := dirname + "/.airbyte/" 70 | 71 | file, _ := os.Open(dirname + "/.airbyte/archive.tar") 72 | r := bufio.NewReader(file) 73 | 74 | gzr, err := gzip.NewReader(r) 75 | if err != nil { 76 | return err 77 | } 78 | defer gzr.Close() 79 | 80 | tr := tar.NewReader(gzr) 81 | 82 | for { 83 | header, err := tr.Next() 84 | 85 | switch { 86 | 87 | // if no more files are found return 88 | case err == io.EOF: 89 | return nil 90 | 91 | // return any other error 92 | case err != nil: 93 | return err 94 | 95 | // if the header is nil, just skip it (not sure how this happens) 96 | case header == nil: 97 | continue 98 | } 99 | 100 | target := filepath.Join(dst, header.Name) 101 | 102 | // Take only airbyte_config folder 103 | if strings.Contains(header.Name, "airbyte_config") { 104 | if err := os.MkdirAll(dirname+"/.airbyte/airbyte_config", 0755); err != nil { 105 | return err 106 | } 107 | 108 | f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode)) 109 | if err != nil { 110 | return err 111 | } 112 | 113 | // copy over contents 114 | if _, err := io.Copy(f, tr); err != nil { 115 | return err 116 | } 117 | 118 | // manually close here after each file operation; defering would cause each file close 119 | // to wait until all operations have completed. 120 | f.Close() 121 | } 122 | } 123 | } 124 | 125 | func CopyConfigToTarget(targetFolder string) error { 126 | files := [3]string{"SOURCE_CONNECTION.yaml", "STANDARD_SYNC.yaml", "DESTINATION_CONNECTION.yaml"} 127 | 128 | dirname, _ := os.UserHomeDir() 129 | 130 | dst := dirname + "/.airbyte/airbyte_config/" 131 | 132 | for _, file := range files { 133 | err := CopyFile(dst+file, targetFolder+"/"+file) 134 | if err != nil { 135 | return err 136 | } 137 | } 138 | 139 | return nil 140 | } 141 | 142 | func CopyFile(from string, to string) error { 143 | sourceFile, err := os.Open(from) 144 | if err != nil { 145 | return err 146 | } 147 | defer sourceFile.Close() 148 | 149 | // Create new file 150 | newFile, err := os.Create(to) 151 | if err != nil { 152 | return err 153 | } 154 | defer newFile.Close() 155 | 156 | _, err = io.Copy(newFile, sourceFile) 157 | 158 | if err != nil { 159 | return err 160 | } 161 | 162 | return nil 163 | } 164 | 165 | func CleanUp() error { 166 | dirname, _ := os.UserHomeDir() 167 | 168 | dst := dirname + "/.airbyte/" 169 | 170 | e := os.Remove(dst + FILE_NAME) 171 | if e != nil { 172 | return e 173 | } 174 | 175 | e = os.RemoveAll(dst + "airbyte_config") 176 | if e != nil { 177 | return e 178 | } 179 | 180 | return nil 181 | } 182 | -------------------------------------------------------------------------------- /common/url_utils.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "errors" 5 | "net/http" 6 | "net/url" 7 | ) 8 | 9 | func isUrl(URL string) bool { 10 | u, err := url.Parse(URL) 11 | return err == nil && u.Scheme != "" && u.Host != "" 12 | } 13 | 14 | func CheckForURL(URL string) (bool, error) { 15 | //Leverage Go's HTTP Post function to make request 16 | if !isUrl(URL) { 17 | return false, errors.New("not in standard URL format") 18 | } 19 | 20 | _, err := http.Get(URL) 21 | 22 | if err != nil { 23 | return false, err 24 | } 25 | 26 | return true, nil 27 | } 28 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/harshithmullapudi/airbyte 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 7 | github.com/jedib0t/go-pretty/v6 v6.2.2 8 | github.com/json-iterator/go v1.1.11 9 | github.com/mitchellh/go-homedir v1.1.0 10 | github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 11 | github.com/spf13/cobra v1.2.1 12 | github.com/spf13/viper v1.8.1 13 | gopkg.in/yaml.v2 v2.4.0 14 | ) 15 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 8 | cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= 9 | cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= 10 | cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= 11 | cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= 12 | cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= 13 | cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= 14 | cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= 15 | cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= 16 | cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= 17 | cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= 18 | cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= 19 | cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= 20 | cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= 21 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 22 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= 23 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= 24 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= 25 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= 26 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 27 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 28 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= 29 | cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= 30 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 31 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= 32 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= 33 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= 34 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 35 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= 36 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= 37 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= 38 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= 39 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 40 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 41 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 42 | github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= 43 | github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2/go.mod h1:VSw57q4QFiWDbRnjdX8Cb3Ow0SFncRw+bA/ofY6Q83w= 44 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 45 | github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= 46 | github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= 47 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 48 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 49 | github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= 50 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 51 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 52 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 53 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 54 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 55 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 56 | github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 57 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 58 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 59 | github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 60 | github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 61 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 62 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 63 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 64 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 65 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 66 | github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= 67 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 68 | github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 69 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 70 | github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= 71 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 72 | github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= 73 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 74 | github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= 75 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 76 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 77 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 78 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 79 | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 80 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 81 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 82 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 83 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 84 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 85 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 86 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 87 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 88 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 89 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 90 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 91 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 92 | github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= 93 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 94 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 95 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 96 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 97 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 98 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 99 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 100 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 101 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 102 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 103 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 104 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 105 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 106 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 107 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 108 | github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= 109 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 110 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 111 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 112 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 113 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 114 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 115 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 116 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 117 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 118 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 119 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 120 | github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 121 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 122 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 123 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 124 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 125 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 126 | github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 127 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 128 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 129 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 130 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 131 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 132 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 133 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 134 | github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 135 | github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 136 | github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 137 | github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 138 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 139 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 140 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 141 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 142 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 143 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 144 | github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= 145 | github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= 146 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 147 | github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 148 | github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= 149 | github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= 150 | github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= 151 | github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= 152 | github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= 153 | github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= 154 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 155 | github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 156 | github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= 157 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 158 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 159 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 160 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 161 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= 162 | github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= 163 | github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= 164 | github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= 165 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 166 | github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 167 | github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 168 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 169 | github.com/jedib0t/go-pretty/v6 v6.2.2 h1:o3McN0rQ4X+IU+HduppSp9TwRdGLRW2rhJXy9CJaCRw= 170 | github.com/jedib0t/go-pretty/v6 v6.2.2/go.mod h1:+nE9fyyHGil+PuISTCrp7avEdo6bqoMwqZnuiK2r2a0= 171 | github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= 172 | github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 173 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 174 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 175 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 176 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 177 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 178 | github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 179 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 180 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 181 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 182 | github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= 183 | github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= 184 | github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= 185 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 186 | github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= 187 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 188 | github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= 189 | github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 190 | github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 191 | github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= 192 | github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 193 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 194 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 195 | github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 196 | github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= 197 | github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= 198 | github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 199 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 200 | github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= 201 | github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 202 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 203 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 204 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 205 | github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= 206 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 207 | github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= 208 | github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= 209 | github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= 210 | github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= 211 | github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= 212 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 213 | github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= 214 | github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= 215 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 216 | github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= 217 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 218 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 219 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 220 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 221 | github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 222 | github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 223 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 224 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 225 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 226 | github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= 227 | github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= 228 | github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= 229 | github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 230 | github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= 231 | github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= 232 | github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= 233 | github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= 234 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 235 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 236 | github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= 237 | github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= 238 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 239 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 240 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 241 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 242 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 243 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 244 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 245 | github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= 246 | github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= 247 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 248 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 249 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 250 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 251 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 252 | go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= 253 | go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= 254 | go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= 255 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 256 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 257 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 258 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 259 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 260 | go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= 261 | go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= 262 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 263 | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 264 | go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= 265 | golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 266 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 267 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 268 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 269 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 270 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 271 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 272 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 273 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 274 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 275 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 276 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 277 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 278 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 279 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 280 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= 281 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= 282 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 283 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 284 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 285 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 286 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 287 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 288 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 289 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 290 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 291 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 292 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 293 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 294 | golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 295 | golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 296 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 297 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 298 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 299 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 300 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 301 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 302 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 303 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 304 | golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 305 | golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 306 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 307 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 308 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 309 | golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 310 | golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 311 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 312 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 313 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 314 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 315 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 316 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 317 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 318 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 319 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 320 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 321 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 322 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 323 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 324 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 325 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 326 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 327 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 328 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 329 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 330 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 331 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 332 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 333 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 334 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 335 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 336 | golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 337 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 338 | golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 339 | golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 340 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 341 | golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= 342 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 343 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 344 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 345 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 346 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 347 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 348 | golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 349 | golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 350 | golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 351 | golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 352 | golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 353 | golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 354 | golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 355 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 356 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 357 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 358 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 359 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 360 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 361 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 362 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 363 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 364 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 365 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 366 | golang.org/x/sys v0.0.0-20180816055513-1c9583448a9c/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 367 | golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 368 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 369 | golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 370 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 371 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 372 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 373 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 374 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 375 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 376 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 377 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 378 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 379 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 380 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 381 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 382 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 383 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 384 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 385 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 386 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 387 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 388 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 389 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 390 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 391 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 392 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 393 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 394 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 395 | golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 396 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 397 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 398 | golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 399 | golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 400 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 401 | golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 402 | golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 403 | golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 404 | golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 405 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 406 | golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 407 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= 408 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 409 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 410 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 411 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 412 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 413 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 414 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 415 | golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 416 | golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= 417 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 418 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 419 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 420 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 421 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 422 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 423 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 424 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 425 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 426 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 427 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 428 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 429 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 430 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 431 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 432 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 433 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 434 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 435 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 436 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 437 | golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 438 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 439 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 440 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 441 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 442 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 443 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 444 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 445 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 446 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 447 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 448 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 449 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 450 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 451 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 452 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 453 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 454 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 455 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 456 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 457 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 458 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 459 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 460 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 461 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 462 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 463 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 464 | golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= 465 | golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 466 | golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 467 | golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 468 | golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 469 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 470 | golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= 471 | golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 472 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 473 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 474 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 475 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 476 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 477 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 478 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 479 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 480 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 481 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 482 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 483 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 484 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 485 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 486 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 487 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 488 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 489 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 490 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= 491 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= 492 | google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= 493 | google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= 494 | google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= 495 | google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= 496 | google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= 497 | google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= 498 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 499 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 500 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 501 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 502 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 503 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 504 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 505 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 506 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 507 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 508 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 509 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 510 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 511 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 512 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 513 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 514 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 515 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 516 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 517 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 518 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 519 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= 520 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 521 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 522 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 523 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 524 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 525 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 526 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 527 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 528 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 529 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= 530 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 531 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= 532 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 533 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 534 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 535 | google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 536 | google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 537 | google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 538 | google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 539 | google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 540 | google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 541 | google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 542 | google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 543 | google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 544 | google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= 545 | google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= 546 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 547 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 548 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 549 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 550 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 551 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 552 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 553 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 554 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 555 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= 556 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 557 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 558 | google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 559 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= 560 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 561 | google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= 562 | google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 563 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 564 | google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 565 | google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= 566 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 567 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 568 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 569 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 570 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 571 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 572 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 573 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 574 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 575 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 576 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 577 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 578 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 579 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 580 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 581 | gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= 582 | gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 583 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 584 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 585 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 586 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 587 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 588 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 589 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 590 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 591 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 592 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 593 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 594 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 595 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 596 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 597 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 598 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= 599 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= 600 | -------------------------------------------------------------------------------- /logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/op/go-logging" 7 | ) 8 | 9 | var Log = logging.MustGetLogger("example") 10 | 11 | var Error = Log.Error 12 | var Errorf = Log.Errorf 13 | var Notice = Log.Notice 14 | var Info = Log.Info 15 | var Debug = Log.Debug 16 | var Warning = Log.Warning 17 | 18 | // Example format string. Everything except the message has a custom color 19 | // which is dependent on the log level. Many fields have a custom output 20 | // formatting too, eg. the time returns the hour down to the milli second. 21 | var format = logging.MustStringFormatter( 22 | `%{color} ▶ %{level:.4s} %{message}`, 23 | ) 24 | 25 | func init() { 26 | // For demo purposes, create two backend for os.Stderr. 27 | backend1 := logging.NewLogBackend(os.Stderr, "", 0) 28 | backend2 := logging.NewLogBackend(os.Stderr, "", 0) 29 | 30 | // For messages written to backend2 we want to add some additional 31 | // information to the output, including the used log level and the name of 32 | // the function. 33 | backend2Formatter := logging.NewBackendFormatter(backend2, format) 34 | 35 | // Only errors and more severe messages should be sent to backend1 36 | backend1Leveled := logging.AddModuleLevel(backend1) 37 | backend1Leveled.SetLevel(logging.ERROR, "") 38 | 39 | // Set the backends to be used. 40 | logging.SetBackend(backend1Leveled, backend2Formatter) 41 | } 42 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright © 2021 NAME HERE 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | package main 17 | 18 | import "github.com/harshithmullapudi/airbyte/cmd" 19 | 20 | func main() { 21 | cmd.Execute() 22 | } 23 | -------------------------------------------------------------------------------- /models/common.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type ErrorResponse struct { 4 | Message string 5 | } 6 | 7 | type CheckResponse struct { 8 | Status string 9 | Message string 10 | JobInfo JobInfo 11 | } 12 | -------------------------------------------------------------------------------- /models/connections.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type Stream struct { 4 | Stream map[string]interface{} 5 | Config map[string]interface{} 6 | } 7 | 8 | type SyncCatalog struct { 9 | Streams []Stream 10 | } 11 | 12 | type Schedule struct { 13 | Units int64 14 | TimeUnit string 15 | } 16 | 17 | type Connection struct { 18 | ConnectionId string 19 | Name string 20 | NamespaceFormat string 21 | Prefix string 22 | SourceId string 23 | DestinationId string 24 | OperationIds []string 25 | SyncCatalog SyncCatalog 26 | Schedule Schedule 27 | Status string 28 | Source Source 29 | Destination Destination 30 | LatestSyncJobCreatedAt int64 31 | LatestSyncJobStatus string 32 | IsSyncing bool 33 | } 34 | 35 | type ConnectionShort struct { 36 | ConnectionId string `yaml:"connectionId"` 37 | Name string `yaml:"name"` 38 | NamespaceFormat string `yaml:"namespaceForm"` 39 | Prefix string `yaml:"prefix"` 40 | SourceId string `yaml:"sourceId"` 41 | DestinationId string `yaml:"destinationId"` 42 | OperationIds []string `yaml:"operationIds"` 43 | Catalog interface{} `yaml:"catalog"` 44 | Manual bool `yaml:"manual"` 45 | Schedule Schedule `yaml:"schedule"` 46 | Status string `yaml:"status"` 47 | } 48 | 49 | type Connections []Connection 50 | 51 | type ConnectionResponse struct { 52 | Connections []Connection 53 | } 54 | 55 | type ConnectionsShort []ConnectionShort 56 | -------------------------------------------------------------------------------- /models/destinations.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type DestinationDefinition struct { 4 | DestinationDefinitionId string 5 | SupportedDestinationSyncModes []string 6 | SupportsDbt bool 7 | SupportsNormalization bool 8 | } 9 | 10 | type Destination struct { 11 | DestinationDefinitionId string `yaml:"destinationDefinitionId"` 12 | DestinationId string `yaml:"destinationId"` 13 | WorkspaceId string `yaml:"workspaceId"` 14 | ConnectionConfiguration map[string]interface{} `yaml:"configuration"` 15 | Name string `yaml:"name"` 16 | DestinationName string `yaml:"destinationName"` 17 | } 18 | 19 | type Destinations []Destination 20 | 21 | type DestinationResponse struct { 22 | Destinations []Destination 23 | } 24 | -------------------------------------------------------------------------------- /models/jobs.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type Attempt struct { 4 | Id int64 5 | Status string 6 | CreatedAt int 7 | UpdatedAt int 8 | EndedAt int 9 | BytesSynced int 10 | RecordsSynced int 11 | } 12 | 13 | type Job struct { 14 | Job JobDetail 15 | Attempts []Attempt 16 | } 17 | 18 | type JobDetail struct { 19 | Id int64 20 | ConfigType string 21 | ConfigId string 22 | CreatedAt int64 23 | UpdatedAt int64 24 | Status string 25 | } 26 | 27 | type JobInfo struct { 28 | *JobDetail 29 | Succeded bool 30 | Logs Logs 31 | } 32 | 33 | type Logs struct { 34 | LogLines []string 35 | } 36 | 37 | type Jobs []Job 38 | 39 | type JobsResponse struct { 40 | Jobs []Job 41 | } 42 | 43 | type ConfigTypes []string 44 | 45 | type Pagination struct { 46 | PageSize int `json:"pageSize"` 47 | RowOffset int `json:"rowOffset"` 48 | } 49 | 50 | type GetAttempt struct { 51 | Attempt Attempt 52 | Logs Logs 53 | } 54 | 55 | type GetJobResponse struct { 56 | Job JobDetail 57 | Attempts []GetAttempt 58 | } 59 | -------------------------------------------------------------------------------- /models/sources.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SourceDefinition struct { 4 | SourceDefinitionId string 5 | Name string 6 | DockerRepository string 7 | DockerImageTag string 8 | DocumentationUrl string 9 | Icon string 10 | } 11 | 12 | type SourceDefinitions []SourceDefinition 13 | type Source struct { 14 | SourceDefinitionId string `yaml:"sourceDefinitionId"` 15 | SourceId string `yaml:"sourceId"` 16 | WorkspaceId string `yaml:"workspaceId"` 17 | ConnectionConfiguration map[string]interface{} `yaml:"configuration"` 18 | Name string `yaml:"name"` 19 | SourceName string `yaml:"sourceName"` 20 | SourceDefinition SourceDefinition 21 | } 22 | 23 | type Sources []Source 24 | 25 | type SourceResponse struct { 26 | Sources Sources 27 | } 28 | 29 | type SourceDefinitionResponse struct { 30 | SourceDefinitions SourceDefinitions 31 | } 32 | 33 | type SourceCheckResponse struct { 34 | Status string 35 | Message string 36 | JobInfo JobInfo 37 | } 38 | 39 | type SourceCheckConfig struct { 40 | SourceDefinitionId string 41 | ConnectionConfiguration map[string]interface{} 42 | } 43 | -------------------------------------------------------------------------------- /models/workspace.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type Workspace struct { 4 | Name string 5 | Email string 6 | WorkspaceId string 7 | Slug string 8 | } 9 | 10 | type Workspaces []Workspace 11 | 12 | type WorkspaceResponse struct { 13 | Workspaces Workspaces 14 | } 15 | --------------------------------------------------------------------------------