{"id":28395218,"url":"https://github.com/databiosphere/terra-folder-manager","last_synced_at":"2025-09-12T12:43:13.106Z","repository":{"id":55136681,"uuid":"238544193","full_name":"DataBiosphere/terra-folder-manager","owner":"DataBiosphere","description":null,"archived":false,"fork":false,"pushed_at":"2021-01-07T20:05:33.000Z","size":120,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":27,"default_branch":"master","last_synced_at":"2025-06-01T06:52:30.916Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DataBiosphere.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-02-05T20:41:06.000Z","updated_at":"2021-12-28T01:24:50.000Z","dependencies_parsed_at":"2022-08-14T13:01:03.745Z","dependency_job_id":null,"html_url":"https://github.com/DataBiosphere/terra-folder-manager","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/DataBiosphere/terra-folder-manager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataBiosphere%2Fterra-folder-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataBiosphere%2Fterra-folder-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataBiosphere%2Fterra-folder-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataBiosphere%2Fterra-folder-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DataBiosphere","download_url":"https://codeload.github.com/DataBiosphere/terra-folder-manager/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DataBiosphere%2Fterra-folder-manager/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262172396,"owners_count":23270000,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-31T19:39:32.576Z","updated_at":"2025-06-27T01:31:23.757Z","avatar_url":"https://github.com/DataBiosphere.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# kernel-service-poc\nThis repository started as a proof-of-concept. It is expanding to serve as a template\nproject for MC Terra services.\n\nIn general, once you copy this project, you can search for the word \"template\" and\nfill in your service or some other appropriate name.\n\n[Deliverybot Dashboard](https://app.deliverybot.dev/DataBiosphere/framework-version/branch/master)\n\n## OpenAPI V3 - formerly swagger\nThe template provides a simple OpenAPI V3 yaml document that includes a /status\nendpoint and a /api/template/v1/ping endpoint. The ping endpoint is there to\nshow the full plumbing for an endpoint that uses the common exception handler to \nreturn an ErrorReport.\n\nThe OpenAPI document also contains two components that we would like to have common\nacross all of our APIs:\n\u003cul\u003e\n\u003cli\u003eErrorReport - a common error return structure\u003c/li\u003e\n\u003cli\u003eSystemStatus - a common response to the /status endpoint\u003c/li\u003e\n\u003c/ul\u003e\n\nA swagger-ui page is available at /api/swagger-ui.html on any running instance. \nTEMPLATE: Once a service has a stable dev/alpha instance, a link to its \nswagger-ui page should go here.\n\n## Spring Boot\nWe use Spring Boot as our framework for REST servers. The objective is to use a minimal set\nof Spring features; there are many ways to do the same thing and we would like to constrain ourselves\nto a common set of techniques.\n\n### Configuration\nWe only use Java configuration. We never use XML files.\n\nIn general, we use type-safe configuration parameters as shown here: \n[Type-safe Configuration Properties](https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-typesafe-configuration-properties).\nThat allows proper typing of parameters read from property files or environment variables. Parameters are\nthen accessed with normal accessor methods. You should never need to use an `@Value` annotation.\n\n### Initialization\nWhen the applications starts, Spring wires up the components based on the profiles in place.\nSetting different profiles allows different components to be included. This technique is used\nas the way to choose the cloud platform (Google, Azure, AWS) code to include.\n\nWe use the Spring idiom of the `postSetupInitialization`, found in ApplicationConfiguration.java,\nto perform initialization of the application between the point of having the entire application initialized and\nthe point of opening the port to start accepting REST requests.\n\n### Annotating Singletons\t\nThe typical pattern when using Spring is to make singleton classes for each service, controller, and DAO.\t\nYou do not have to write the class with its own singleton support. Instead, annotate the class with\t\nthe appropriate Spring annotation. Here are ones we use:\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e@Component\u003c/code\u003e Regular singleton class, like a service.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e@Repository\u003c/code\u003e DAO component\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e@Controller\u003c/code\u003e REST Controller\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e@Configuration\u003c/code\u003e Definition of properties\u003c/li\u003e\n\u003c/ul\u003e\n\n### Common Annotations\nThere are other annotations that are handy to know about.\n\n#### Autowiring\nSpring wires up the singletons and other beans when the application is launched.\nThat allows us to use Spring profiles to control the collection of code that is\nrun for different environments. Perhaps obviously, you can only autowire singletons to each other. You cannot autowire\ndynamically created objects.\n\nThere are two styles for declaring autowiring.\nThe preferred method of autowiring, is to put the annotation on the constructor\nof the class. Spring will autowire all of the inputs to the constructor.\n```\n@Component\npublic class Foo {\n    private Bar bar;\n    private Fribble fribble;\n\n    @Autowired\n    public Foo(Bar bar, Fribble fribble) {\n        this.bar = bar;\n        this.foo = foo;\n    }\n```\nSpring will pass in the instances of Bar and Fribble into the constructor.\nIt is possible to autowire a specific class member, but that is rarely necessary:\n```\n@Component\npublic class Foo {\n    @Autowired\n    private Bar bar;\n```\n\n#### REST Annotations\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e@RequestBody\u003c/code\u003e Marks the controller input parameter receiving the body of the request\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e@PathVariable(\"x\")\u003c/code\u003e Marks the controller input parameter receiving the parameter \u003ccode\u003ex\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e@RequestParam(\"y\")\u003c/code\u003e Marks the controller input parameter receiving the query parameter\u003ccode\u003ey\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n#### JSON Annotations\nWe use the Jackson JSON library for serializing objects to and from JSON. Most of the time, you don't need to \nuse JSON annotations. It is sufficient to provide setter/getter methods for class members\nand let Jackson figure things out with interospection. There are cases where it needs help\nand you have to be specific.\n\nThe common JSON annotations are:\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e@JsonValue\u003c/code\u003e Marks a class member as data that should be (de)serialized to(from) JSON.\nYou can specify a name as a parameter to specify the JSON name for the member.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e@JsonIgnore\u003c/code\u003e  Marks a class member that should not be (de)serialized\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e@JsonCreator\u003c/code\u003e Marks a constructor to be used to create an object from JSON.\u003c/li\u003e\n\u003c/ul\u003e\n\nFor more details see [Jackson JSON Documentation](https://github.com/FasterXML/jackson-docs)\n\n## Main Code Structure\nThis section explains the code structure of the template. Here is the directory structure:\n```\n/src\n  /main\n    /java\n      /bio/terra/TEMPLATE\n        /app\n          /configuration\n          /controller\n        /common\n          /exception\n        /service\n          /ping\n    /resources\n```\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e/app\u003c/code\u003e For the top of the application, including Main and the StartupInitializer\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e/app/configuration\u003c/code\u003e For all of the bean and property definitions\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e/app/controller\u003c/code\u003e For the REST controllers. The controllers typically do very little.\nThey invoke a service to do the work and package the service output into the response. The\ncontroller package also defines the global exception handling.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e/common\u003c/code\u003e For common models and common exceptions; for example, a model that is \nshared by more than one service.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e/common/exception\u003c/code\u003e The template provides abstract base classes for the commonly\nused HTTP status responses. They are all based on the ErrorReportException that provides the\nexplicit HTTP status and \"causes\" information for our standard ErrorReport model.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e/service\u003c/code\u003e Each service gets a package within. We handle cloud-platform specializations\nwithin each service.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e/service/ping\u003c/code\u003e The example service; please delete.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e/resources\u003c/code\u003e Properties definitions, database schema definitions, and the REST API definition\u003c/li\u003e\n\u003c/ul\u003e\n\n## Test Structure\nThere are sample tests for the ping service to illustrate two styles of unit testing.\n\n## Deployment\n### On commit to master\n1. New commit is merged to master\n2. [The master_push workflow](https://github.com/DataBiosphere/kernel-service-poc/blob/gm-deployment/.github/workflows/master_push.yml) is triggered. It builds the image, tags the image \u0026 commit, and pushes the image to GCR. It then sends a [dispatch](https://help.github.com/en/actions/reference/events-that-trigger-workflows#external-events-repository_dispatch) with the new version for the service to the [framework-version repo](https://github.com/DataBiosphere/framework-version).\n3. This triggers the [update workflow](https://github.com/DataBiosphere/framework-version/blob/master/.github/workflows/update.yml), which updates the JSON that maps services to versions to map to the new version for the service whose repo sent the dispatch. The JSON is then committed and pushed.\n4. This triggers the [tag workflow](https://github.com/DataBiosphere/framework-version/blob/master/.github/workflows/tag.yml), which tags the new commit in the framework-version repo with a bumped semantic version, yielding a new version of the whole stack incorporating the newly available version of the service.\n5. The new commit corresponding to the above version of the stack is now visible on the [deliverybot dashboard](https://app.deliverybot.dev/DataBiosphere/framework-version/branch/master). It can now be manually selected for deployment to an environment.\n6. Deploying a version of the stack to an environment from the dashboard triggers the [deploy workflow](https://github.com/DataBiosphere/framework-version/blob/master/.github/workflows/deploy.yml). This sends a dispatch to the [framework-env repo](https://github.com/DataBiosphere/framework-env) with the version that the chosen commit is tagged with, and the desired environment.\n7. The dispatch triggers the [update workflow in that repo](https://github.com/DataBiosphere/framework-env/blob/master/.github/workflows/update.yml), which similarly to the one in the framework-version one, updates a JSON. This JSON maps environments to versions of the stack. It is updated to reflect the desired deployment of the new stack version to the specified environment and the change is pushed up.\n8. The change to the JSON triggers the [apply workflow](https://github.com/DataBiosphere/framework-env/blob/master/.github/workflows/apply.yml), which actually deploys the desired resources to k8s. It determines the services that must be updated by diffing the stack versions that the environment in question is transitioning between and re-deploys the services that need updates.\n\n### Using cloud code and skaffold\n\nOnce you have deployed to GKE, if you are developing on the API it might be useful to update the API container image\nwithout having to go through a full re-deploy of the Kubernetes namespace. CloudCode for IntelliJ makes this simple.\nCode for local development lives in the `local-dev` directory.\nFirst install [skaffold](https://github.com/GoogleContainerTools/skaffold):\n\n    brew install skaffold\n\nNext, [enable the CloudCode plugin for IntelliJ](https://cloud.google.com/code/docs/intellij/quickstart-IDEA).\n\nFinally, run `local-dev/setup_local_env.sh \u003cyour dev environment name\u003e`. This \nis a small script that clones the latest environment configuration kustomizations\nfrom [github.com/databiosphere/kernel-poc-service-config](github.com/databiosphere/kernel-poc-service-config)\nand sets up your local skaffold.yaml file.\n\nThen you should be able to either `Deploy to Kubernetes` or `Develop on Kubernetes` from the run configurations menu.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatabiosphere%2Fterra-folder-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdatabiosphere%2Fterra-folder-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdatabiosphere%2Fterra-folder-manager/lists"}