-
Notifications
You must be signed in to change notification settings - Fork 25
Using the Rails console to debug the cf api server
Sometimes it can be handy to start up an interactive REPL for debugging the current state of the Cloud Controller API. You can do this in cf-for-k8s with kubectl exec
.
First we start an interactive shell with the /cnb/lifecycle/launcher
to load required env vars and PATH
kubectl exec -it -n cf-system cf-api-server-5f454f986b-4gdbx -c cf-api-server -- /cnb/lifecycle/launcher /bin/bash
/workspace/bin/console /config/cloud_controller_ng.yml
Now you can execute Ruby / Cloud Controller code with full access to the rest of the system. E.g.
You can load various records from the database to observe and interact with them.
cnb@cf-api-server-5f454f986b-4gdbx:/workspace$ /workspace/bin/console /config/cloud_controller_ng.yml
From: /workspace/lib/cloud_controller/console.rb:53 :
48:
49: module VCAP::CloudController
50: # rubocop:disable Lint/Debugger
51: binding.pry quiet: true
52: # rubocop:enable Lint/Debugger
=> 53: end
[1] pry(VCAP::CloudController)> Domain.first
=> #<VCAP::CloudController::SharedDomain @values={:id=>1, :guid=>"a92e85d7-487c-4854-a21a-72e14f17eee2", :created_at=>2021-01-27 18:27:38 UTC, :updated_at=>2021-01-27 18:27:38 UTC, :name=>"apps.tim.k8s.capi.land", :wildcard=>true, :owning_organization_id=>nil, :router_group_guid=>nil, :internal=>false}>
[2] pry(VCAP::CloudController)> Route.first
=> #<VCAP::CloudController::Route @values={:id=>1, :guid=>"a38c12cb-65ef-4fef-b531-031ea1261668", :created_at=>2021-01-27 18:41:39 UTC, :updated_at=>2021-01-27 18:41:39 UTC, :host=>"catnip", :domain_id=>1, :space_id=>1, :path=>"", :port=>0, :vip_offset=>nil}>
You can instantiate client instances to interact with other services like UAA, Eirini, and the Kubernetes API.
Here's an example of fetching a Route
from the K8s API:
CloudController::DependencyLocator.instance.k8s_api_client.get_route(Route.first.guid, 'cf-workloads')
=> #<Kubeclient::Resource apiVersion="networking.cloudfoundry.org/v1alpha1", kind="Route", metadata={:creationTimestamp=>"2021-01-27T18:41:39Z", :finalizers=>["routes.networking.cloudfoundry.org"], :generation=>3, :labels=>{:"app.kubernetes.io/component"=>"cf-networking", :"app.kubernetes.io/managed-by"=>"cloudfoundry", :"app.kubernetes.io/name"=>"a38c12cb-65ef-4fef-b531-031ea1261668", :"app.kubernetes.io/part-of"=>"cloudfoundry", :"app.kubernetes.io/version"=>"0.0.0", :"cloudfoundry.org/domain_guid"=>"a92e85d7-487c-4854-a21a-72e14f17eee2", :"cloudfoundry.org/org_guid"=>"0a64ea09-7780-4ee2-a281-53d501ed6faa", :"cloudfoundry.org/route_guid"=>"a38c12cb-65ef-4fef-b531-031ea1261668", :"cloudfoundry.org/space_guid"=>"2471d6b6-6996-4db6-b1b9-356823513b38"}, :name=>"a38c12cb-65ef-4fef-b531-031ea1261668", :namespace=>"cf-workloads", :resourceVersion=>"11542", :selfLink=>"/apis/networking.cloudfoundry.org/v1alpha1/namespaces/cf-workloads/routes/a38c12cb-65ef-4fef-b531-031ea1261668", :uid=>"70176633-b6d2-47c5-8a16-2c559933e419"}, spec={:destinations=>[{:app=>{:guid=>"4a9361e0-5996-4116-9c7b-fb7b8eb6cca0", :process=>{:type=>"web"}}, :guid=>"08bbc361-e171-427b-a69a-be1a5ecc0c92", :port=>8080, :selector=>{:matchLabels=>{:"cloudfoundry.org/app_guid"=>"4a9361e0-5996-4116-9c7b-fb7b8eb6cca0", :"cloudfoundry.org/process_type"=>"web"}}}], :domain=>{:internal=>false, :name=>"apps.tim.k8s.capi.land"}, :host=>"catnip", :url=>"catnip.apps.tim.k8s.capi.land"}>
You can quickly see what methods are available on an object with the following technique:
CloudController::DependencyLocator.instance.k8s_api_client.methods - Object.methods
=> [:get_image,
:update_image,
:delete_image,
:create_route,
:get_route,
:update_route,
:delete_route,
:update_builder,
:create_builder,
:delete_builder,
:get_builder,
:create_image]
This essentially subtracts all the methods from the base Object
Class leaving you with a list of the ones (mostly) unique to your Class.
To view more information about a particular method you can use the pry
command show-method
. For example:
show-method CloudController::DependencyLocator.instance.k8s_api_client.get_route
From: /workspace/lib/kubernetes/api_client.rb:58:
Owner: Kubernetes::ApiClient
Visibility: public
Signature: get_route(name, namespace)
Number of lines: 10
def get_route(name, namespace)
@route_kube_client.get_route(name, namespace)
rescue Kubeclient::ResourceNotFoundError
nil
rescue Kubeclient::HttpError => e
logger.error('get_route', error: e.inspect, response: e.response, backtrace: e.backtrace)
error = CloudController::Errors::ApiError.new_from_details('KubernetesRouteResourceError', name)
error.set_backtrace(e.backtrace)
raise error
end
There's a lot you can do with pry
such as setting break points, stepping into and out of functions, viewing docs, and more which you can discover by reading pry cheat sheets and tutorials.