github.com/GoogleContainerTools/skaffold/v2@v2.13.2/docs-v1/content/en/docs/design/api.md (about) 1 --- 2 title: "Skaffold API" 3 linkTitle: "Skaffold API" 4 weight: 60 5 6 7 featureId: api 8 9 --- 10 When running [`skaffold dev`]({{< relref "/docs/workflows/dev" >}}) or [`skaffold debug`]({{< relref "/docs/workflows/debug" >}}), 11 Skaffold starts a server that exposes an API over the lifetime of the Skaffold process. 12 Besides the CLI, this API is the primary way tools like IDEs integrate with Skaffold for **retrieving information about the 13 pipeline** and for **controlling the phases in the pipeline**. 14 15 To retrieve information about the Skaffold pipeline, the Skaffold API provides two main functionalities: 16 17 * A [streaming event log]({{< relref "#events-api">}}) created from the different phases in a pipeline run, and 18 19 * A snapshot of the [overall state]({{< relref "#state-api" >}}) of the pipeline at any given time during the run. 20 21 To control the individual phases of the Skaffold, the Skaffold API provides [fine-grained control]({{< relref "#control-api" >}}) 22 over the individual phases of the pipeline (build, deploy, and sync). 23 24 ## Connecting to the Skaffold API 25 The Skaffold API is `gRPC` based, and it is also exposed via the gRPC gateway as a JSON over HTTP service. 26 27 The API can be enabled via setting the `--rpc-port` or `--rpc-http-port` flags (or both) 28 depending on whether you want to enable the gRPC API or the HTTP REST API, respectively. 29 30 31 {{< alert title="Note">}} 32 The `--enable-rpc` flag is now deprecated in favor of `--rpc-port` and `--rpc-http-port` flags. 33 {{</alert>}} 34 35 36 For reference, we generate the server's [gRPC service definitions and message protos]({{< relref "/docs/references/api/grpc" >}}) as well as the [Swagger based HTTP API Spec]({{< relref "/docs/references/api/swagger" >}}). 37 38 ## gRPC Server 39 40 The gRPC API can be started by specifying the `--rpc-port` flag. If the specified port is not available, Skaffold will 41 exit with failure. 42 43 ### HTTP server 44 45 The HTTP REST API can be started by specifying the `--rpc-http-port` flag. If the specified port is not available, 46 Skaffold will exit with failure. 47 48 Starting the HTTP REST API will also start the gRPC API as it proxies the requests to the gRPC API. By default, Skaffold 49 chooses a random available port for gRPC, but it can be customized (see below). 50 51 #### Creating a gRPC Client 52 53 To connect to the `gRPC` server at the specified port, create a client using the following code snippet. 54 55 {{< alert title="Note" >}} 56 The skaffold gRPC server is not compatible with HTTPS, so connections need to be marked as insecure with `grpc.WithInsecure()` 57 {{</alert>}} 58 59 ```golang 60 import ( 61 "log" 62 pb "github.com/GoogleContainerTools/skaffold/proto/v1" 63 "google.golang.org/grpc" 64 ) 65 66 func main(){ 67 conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure()) 68 if err != nil { 69 log.Fatalf("fail to dial: %v", err) 70 } 71 defer conn.Close() 72 client := pb.NewSkaffoldServiceClient(conn) 73 } 74 ``` 75 76 77 ## API Structure 78 79 Skaffold's API exposes the three main endpoints: 80 81 * Event API - continuous stream of lifecycle events 82 * State API - retrieve the current state 83 * Control API - control build/deploy/sync 84 85 ### Event API 86 87 Skaffold provides a continuous development mode, [`skaffold dev`]({{< relref "/docs/workflows/dev" >}}), which rebuilds and redeploys 88 your application on changes. In a single development loop, one or more container images 89 may be built and deployed. 90 91 Skaffold exposes events for clients to be notified when phases within a development loop 92 start, succeed, or fail. 93 Tools that integrate with Skaffold can use these events to kick off parts of a development workflow depending on them. 94 95 Example scenarios: 96 97 * port-forwarding events are used by Cloud Code to automatically attach debuggers to running containers. 98 * using an event indicating a frontend service has been deployed and port-forwarded successfully to 99 kick off a suite of Selenium tests against the newly deployed service. 100 101 **Event API Contract** 102 103 | protocol | endpoint | encoding | 104 | ---- | --- | --- | 105 | HTTP | `http://localhost:{HTTP_RPC_PORT}/v1/events` | newline separated JSON using chunk transfer encoding over HTTP| 106 | gRPC | `client.Events(ctx)` method on the [`SkaffoldService`]({{< relref "/docs/references/api#skaffoldservice">}}) | protobuf 3 over HTTP | 107 108 109 **Examples** 110 111 {{% tabs %}} 112 {{% tab "HTTP API" %}} 113 Using `curl` and `HTTP_RPC_PORT=50052`, an example output of a `skaffold dev` execution on our [getting-started example](https://github.com/GoogleContainerTools/skaffold/tree/main/examples/getting-started) 114 ```bash 115 curl localhost:50052/v1/events 116 {"result":{"timestamp":"2019-10-16T18:26:11.385251549Z","event":{"metaEvent":{"entry":"Starting Skaffold: {Version:v0.39.0-16-g5bb7c9e0 ConfigVersion:skaffold/v1 GitVersion: GitCommit:5bb7c9e078e4d522a5ffc42a2f1274fd17d75902 GitTreeState:dirty BuildDate:2019-10-03T15:01:29Z GoVersion:go1.13rc1 Compiler:gc Platform:linux/amd64}"}}}} 117 {"result":{"timestamp":"2019-10-16T18:26:11.436231589Z","event":{"buildEvent":{"artifact":"gcr.io/k8s-skaffold/skaffold-example","status":"In Progress"}},"entry":"Build started for artifact gcr.io/k8s-skaffold/skaffold-example"}} 118 {"result":{"timestamp":"2019-10-16T18:26:12.010124246Z","event":{"buildEvent":{"artifact":"gcr.io/k8s-skaffold/skaffold-example","status":"Complete"}},"entry":"Build completed for artifact gcr.io/k8s-skaffold/skaffold-example"}} 119 {"result":{"timestamp":"2019-10-16T18:26:12.391721823Z","event":{"deployEvent":{"status":"In Progress"}},"entry":"Deploy started"}} 120 {"result":{"timestamp":"2019-10-16T18:26:12.847239740Z","event":{"deployEvent":{"status":"Complete"}},"entry":"Deploy complete"}} 121 .. 122 ``` 123 {{% /tab %}} 124 {{% tab "gRPC API" %}} 125 To get events from the API using `gRPC`, first create a [`gRPC` client]({{< relref "#creating-a-grpc-client" >}}). 126 then, call the `client.Events()` method: 127 128 ```golang 129 func main() { 130 ctx, ctxCancel := context.WithCancel(context.Background()) 131 defer ctxCancel() 132 // `client` is a gRPC client with connection to localhost:50051. 133 logStream, err := client.Events(ctx, &empty.Empty{}) 134 if err != nil { 135 log.Fatalf("could not get events: %v", err) 136 } 137 for { 138 entry, err := logStream.Recv() 139 if err == io.EOF { 140 break 141 } 142 if err != nil { 143 log.Fatal(err) 144 } 145 log.Println(entry) 146 } 147 } 148 ``` 149 {{% /tab %}} 150 {{% /tabs %}} 151 152 Each [Entry]({{<relref "/docs/references/api/grpc#proto.LogEntry" >}}) in the log contains an [Event]({{< relref "/docs/references/api/grpc#proto.Event" >}}) in the `LogEntry.Event` field and 153 a string description of the event in `LogEntry.entry` field. 154 155 156 ### State API 157 158 The State API provides a snapshot of the current state of the following components: 159 160 - build state per artifacts 161 - deploy state 162 - file sync state 163 - status check state per resource 164 - port-forwarded resources 165 166 **State API Contract** 167 168 | protocol | endpoint | encoding | 169 | ---- | --- | --- | 170 | HTTP | `http://localhost:{HTTP_RPC_PORT}/v1/state` | newline separated JSON using chunk transfer encoding over HTTP| 171 | gRPC | `client.GetState(ctx)` method on the [`SkaffoldService`]({{< relref "/docs/references/api/grpc#skaffoldservice">}}) | protobuf 3 over HTTP | 172 173 174 **Examples** 175 {{% tabs %}} 176 {{% tab "HTTP API" %}} 177 Using `curl` and `HTTP_RPC_PORT=50052`, an example output of a `skaffold dev` execution on our [microservices example](https://github.com/GoogleContainerTools/skaffold/tree/main/examples/microservices) 178 ```bash 179 curl localhost:50052/v1/state | jq 180 { 181 "buildState": { 182 "artifacts": { 183 "gcr.io/k8s-skaffold/leeroy-app": "Complete", 184 "gcr.io/k8s-skaffold/leeroy-web": "Complete" 185 } 186 }, 187 "deployState": { 188 "status": "Complete" 189 }, 190 "forwardedPorts": { 191 "9000": { 192 "localPort": 9000, 193 "remotePort": 8080, 194 "namespace": "default", 195 "resourceType": "deployment", 196 "resourceName": "leeroy-web" 197 }, 198 "50055": { 199 "localPort": 50055, 200 "remotePort": 50051, 201 "namespace": "default", 202 "resourceType": "service", 203 "resourceName": "leeroy-app" 204 } 205 }, 206 "statusCheckState": { 207 "status": "Succeeded" 208 }, 209 "fileSyncState": { 210 "status": "Not Started" 211 } 212 } 213 ``` 214 {{% /tab %}} 215 {{% tab "gRPC API" %}} 216 To retrieve the state from the server using `gRPC`, first create [`gRPC` client]({{< relref "#creating-a-grpc-client" >}}). 217 Then, call the `client.GetState()` method: 218 219 ```golang 220 func main() { 221 // Create a gRPC client connection to localhost:50051. 222 // See code above 223 ctx, ctxCancel := context.WithCancel(context.Background()) 224 defer ctxCancel() 225 grpcState, err = client.GetState(ctx, &empty.Empty{}) 226 ... 227 } 228 ``` 229 {{% /tab %}} 230 {{% /tabs %}} 231 232 ### Control API 233 234 By default, [`skaffold dev`]({{< relref "/docs/workflows/dev" >}}) will automatically build artifacts, deploy manifests and sync files on every source code change. 235 However, this behavior can be paused and individual actions can be gated off by user input through the Control API. 236 237 With this API, users can tell Skaffold to wait for user input before performing any of these actions, 238 even if the requisite files were changed on the filesystem. By doing so, users can "queue up" changes while 239 they are iterating locally, and then have Skaffold rebuild and redeploy only when asked. This can be very 240 useful when builds are happening more frequently than desired, when builds or deploys take a long time or 241 are otherwise very costly, or when users want to integrate other tools with `skaffold dev`. 242 243 The automation can be turned off or on using the Control API, or with `auto-build` flag for building, `auto-deploy` flag for deploys, and the `auto-sync` flag for file sync. 244 If automation is turned off for a phase, Skaffold will wait for a request to the Control API before executing the associated action. 245 246 Each time a request is sent to the Control API by the user, the specified actions in the payload are executed immediately. 247 This means that _even if there are new file changes_, Skaffold will wait for another user request before executing any of the given actions again. 248 249 **Control API Contract** 250 251 | protocol | endpoint | 252 | --- | --- | 253 | HTTP, method: POST | `http://localhost:{HTTP_RPC_PORT}/v1/execute`, the [Execution Service]({{<relref "/docs/references/api/swagger#/SkaffoldService/Execute">}}) | 254 | gRPC | `client.Execute(ctx)` method on the [`SkaffoldService`]({{< relref "/docs/references/api/grpc#skaffoldservice">}}) | 255 | HTTP, method: PUT | `http://localhost:{HTTP_RPC_PORT}/v1/build/auto_execute`, the [Auto Build Service]({{<relref "/docs/references/api/swagger#/SkaffoldService/AutoBuild">}}) | 256 | gRPC | `client.AutoBuild(ctx)` method on the [`SkaffoldService`]({{< relref "/docs/references/api/grpc#skaffoldservice">}}) | 257 | HTTP, method: PUT | `http://localhost:{HTTP_RPC_PORT}/v1/sync/auto_execute`, the [Auto Sync Service]({{<relref "/docs/references/api/swagger#/SkaffoldService/AutoSync">}}) | 258 | gRPC | `client.AutoSync(ctx)` method on the [`SkaffoldService`]({{< relref "/docs/references/api/grpc#skaffoldservice">}}) | 259 | HTTP, method: PUT | `http://localhost:{HTTP_RPC_PORT}/v1/deploy/auto_execute`, the [Auto Deploy Service]({{<relref "/docs/references/api/swagger#/SkaffoldService/AutoDeploy">}}) | 260 | gRPC | `client.AutoDeploy(ctx)` method on the [`SkaffoldService`]({{< relref "/docs/references/api/grpc#skaffoldservice">}}) | 261 262 263 **Examples** 264 265 {{% tabs %}} 266 {{% tab "HTTP API" %}} 267 268 Using our [Quickstart example]({{< relref "/docs/quickstart" >}}), we can start skaffold with `skaffold dev --auto-build=false`. 269 When we change `main.go`, Skaffold will notice file changes but will not rebuild the image until it receives a request to the Control API with `{"build": true}`: 270 271 ```bash 272 curl -X POST http://localhost:50052/v1/execute -d '{"build": true}' 273 ``` 274 275 At this point, Skaffold will wait to deploy the newly built image until we invoke the Control API with `{"deploy": true}`: 276 277 ```bash 278 curl -X POST http://localhost:50052/v1/execute -d '{"deploy": true}' 279 ``` 280 281 These steps can also be combined into a single request: 282 283 ```bash 284 curl -X POST http://localhost:50052/v1/execute -d '{"build": true, "deploy": true}' 285 ``` 286 287 We can make Skaffold start noticing file changes automatically again by issuing the requests: 288 289 ```bash 290 curl -X PUT http://localhost:50052/v1/build/auto_execute -d '{"enabled": true}' 291 curl -X PUT http://localhost:50052/v1/deploy/auto_execute -d '{"enabled": true}' 292 ``` 293 294 {{% /tab %}} 295 {{% tab "gRPC API" %}} 296 To access the Control API via the `gRPC`, create [`gRPC` client]({{< relref "#creating-a-grpc-client" >}}) as before. 297 Then, use the `client.Execute()` method with the desired payload to trigger it once: 298 299 ```golang 300 func main() { 301 ctx, ctxCancel := context.WithCancel(context.Background()) 302 defer ctxCancel() 303 // `client` is the gRPC client with connection to localhost:50051. 304 _, err = client.Execute(ctx, &pb.UserIntentRequest{ 305 Intent: &pb.Intent{ 306 Build: true, 307 Sync: true, 308 Deploy: true, 309 }, 310 }) 311 if err != nil { 312 log.Fatalf("error when trying to execute phases: %v", err) 313 } 314 } 315 ``` 316 Use the `client.AutoBuild()`,`client.AutoSync()` and `client.AutoDeploy()` method to enable or disable auto build, auto sync and auto deploy: 317 318 ```golang 319 func main() { 320 ctx, ctxCancel := context.WithCancel(context.Background()) 321 defer ctxCancel() 322 // `client` is the gRPC client with connection to localhost:50051. 323 _, err = client.AutoBuild(ctx, &pb.TriggerRequest{ 324 State: &pb.TriggerState{ 325 Val: &pb.TriggerState_Enabled{ 326 Enabled: true, 327 }, 328 }, 329 }) if err != nil { 330 log.Fatalf("error when trying to auto trigger phases: %v", err) 331 } 332 } 333 ``` 334 {{% /tab %}} 335 {{% /tabs %}}