Cloud customer?
Start for Free >
Upgrade in MyJFrog >
What's New in Cloud >







Overview

Requires an Enterprise or Enterprise+ license.

Mission Control exposes a rich REST API to allow fully automated management of registered JFrog Platform Deployments (JPDs).

This provides a convenient and up-to-date self-descriptive API and can be used by various tools to automate administration and configuration actions.

Base URL

The Platform REST URL is constructed of: 

<JFrog URL>/<Service Context>/api/<API-Version>

For example

# Using your JFrog URL 
http://myjfrog.acme.org/mc/api/v1

# Using your Artifactory server hostname and the Artifactory router port
http://ARTIFACTORY_SERVER_HOSTNAME:8082/mc/api/v1

Authentication

Mission Control's REST API supports authentication types:

TypeDescription
Access Token

Users have to use access token as a bearer token in the authorization header.

Example of authentication using the Bearer token:

    1. Create an admin Access Token to use for Mission Control in the JFrog Platform UI. For more information, see Generating Admin Tokens.

    2. Run.

       curl http://localhost:8082/mc/api/v1/jpds -H 'Authorization: Bearer <token>'
      



Usage


Mission Control REST API can be invoked in any of the standard ways for a REST API. The following section describes how to use the Mission Control REST API using cURL as an example.

Using cURL 

You can download cURL here. Learn how to use and configure cURL here.
Example - Create JPD

The example below demonstrates how to invoke the create user REST API.

  • You have MissionControl  running within your local JPD

  • You wish to create another JPD called "us-west"

  • You created a file with the site's parameters called createjpd.json

To use the file to register this new JPD, you would use the following command:

Using cURL with the REST API
$ curl -X POST 'http://localhost:8082/mc/api/v1/jpds' -H 'Authorization: Bearer <token>'  -H 'Content-Type: application/json; charset=UTF-8' -T createjpd.json
The file createsite.json will contain the following :
{
    "name": "us-west",
    "url" : "http://somehost",
    "token" : "xxx",
    "location": {
        "city_name": "Sunnyvale",
        "country_code": "US",
        "latitude": 37.368830,
        "longitude": -122.036350
    }
}
Page Contents






SYSTEM 

Export

Description: Export Mission Control data to a JSON file encrypted with the master key. 
Since: 4.0
Usage: PUT /api/v1/system/backup/export
Produces: text/plain

Return codes:

204 - Encrypted JSON file created at $JFROG_HOME/var/backup/mc/export.json 
500 - Error during export


Sample Output:

PUT /api/v1/backup/export  
OK

Import

Description: Import Mission Control data from a JSON file encrypted with the master key. 
Since: 4.0
Usage: PUT /api/v1/system/backup/import
Produces: text/plain

Return codes:

204 - Successfully imported JSON file at $JFROG_HOME/var/backup/mc/export.json into the database
400 - JSON file is not in the correct format
500 - Error during import


Sample Output:

PUT /api/v1/backup/import
OK

System Health Check

Description: Get an indication if Mission Control is running or not. No authentication required. 
Since: 4.0
Usage: GET /api/v1/system/ping
Produces: text/plain
Sample Output:

GET /api/v1/system/ping  
OK



JPDs 


Add JPD 

Description: Adds  a new JPD to Mission Control. In 4.x, it is no longer necessary to register individual services. When a JPD is registered, Mission Control queries for all the services installed in the JPD. This list is updated periodically and is also used to get the status of the individual services installed in the JPD. The location information is also associated with the JPD. This replaces both Sites and Services APIs in the prior versions.
Since: 4.0
Notes: Requires Artifactory Enterprise
Security: Requires an admin user
Usage: POST /mc/api/v1/jpds

Return codes:

201 - Created
400 -  Failed to connect to the JPD. Please verify that the JPD information provided is correct
409 - Conflicts with an existing JPD (URL, name)

Consumes: application/json


{
+  "name" : "<JPD name>",
+  "url" : "<JPD URL>",                   // The JPD base URL
+  "token" : "<Join Key>",                // The JPD join key 
+  "location" : {
+    "city_name" : "<City name>",
+    "country_code" : "<Country code>",
+    "latitude" : <Latitude>,
+    "longitude" : <Longitude>
  },
-  "tags" : [ "<Tag 0>", "<Tag 1>" ]
}



+=mandatory; -=optional

Sample Usage:


POST /api/v1/jpds
{
    "name" : "dev-west",
    "url" : "https://artifactory-west.acme.com",
    "token" : "<Join token>",
    "location" : {
		"city_name" : "San Francisco",
	    "country_code" : "US",
	    "latitude" : 37.7749,
	    "longitude" : 122.4194
	},
   "tags" : [ "prod", "dev" ]
}

To add a legacy JPD (Artifactory 6.x)

POST /api/v1/jpds
{
+  "name" : "<JPD name>",
+  "url" : "<JPD URL>",                   // The JPD base URL
+  "username" : "<admin username>",               
+  "password" : "<admin pasword>",                
+  "location" : {
+    "city_name" : "<City name>",
+    "country_code" : "<Country code>",
+    "latitude" : <Latitude>,
+    "longitude" : <Longitude>
  },
-  "tags" : [ "<Tag 0>", "<Tag 1>" ]
}


Update JPD


Description: Updates a JPD give its id.

Since: 4.0
Notes: Requires Artifactory Enterprise
Security: Requires an admin user
Usage: PUT /mc/api/v1/jpds/{id}

Return codes:

204 - No Content
400 -  Failed to connect to the JPD. Please verify that the JPD information provided is correct
409 - Conflicts with an existing JPD (URL, name)
Consumes: application/json


{
+  "name" : "<JPD name>",
+  "url" : "<JPD URL>",                   // The JPD base URL
-  "token" : "<Join Key>",                // The JPD join key 
+  "location" : {
+    "city_name" : "<City name>",
+    "country_code" : "<Country code>",
+    "latitude" : <Latitude>,
+    "longitude" : <Longitude>
  },
-  "tags" : [ "<Tag 0>", "<Tag 1>" ]
}

+=mandatory; -=optional


Sample Usage:

PUT /api/v1/jpds/JPD-3
{
  "name" : "new_name",
  "url" : "http://new-jpd-url:8080/jpd.test",
  "location" : {
    "city_name" : "Toulouse",
    "country_code" : "FR",
    "latitude" : 43.6043,
    "longitude" : 1.4437
  }
}

Get JPD List

Description: Get a list of all JPDs, optionnaly filtering them according to tag, name, url or status. Those filters can contain the wildcard *.

Since: 4.0
Notes: Requires Artifactory Enterprise
Security: Requires an admin user
Usage: GET /mc/api/v1/jpds?[name={some_name}][&tag={some_tag}][&url={some_url}][&status={ONLINE|OFFLINE|PARTIAL|UNAUTHORIZED}]
Produces: application/json
Return codes:
200 - Success


Sample Usage:

GET /api/v1/jpds
[ {
    "id": "JPD-1",
    "licenses": [
      {
        "expired": false,
        "license_hash": "2c2ef96d8a90ea2bb91287258dc8ab72a6b0f749",
        "licensed_to": "jfrog.com",
        "type": "ENTERPRISE_PLUS_TRIAL",
        "valid_through": "2020-02-14"
      }
    ],
    "location": {
      "city_name": "Nuuk",
      "country_code": "GL",
      "latitude": 64.18347,
      "longitude": -51.72157
    },
    "name": "HOME",
    "services": [
      {
        "status": {
          "code": "ONLINE"
        },
        "type": "ARTIFACTORY"
      },
      {
        "status": {
          "code": "ONLINE"
        },
        "type": "JFMC"
      }
    ],
    "status": {
      "code": "ONLINE",
      "message": "All services are online",
      "warnings": []
    },
    "tags": [],
    "url": "http://jpd.local/"
  } ]

Get JPD by id

Description: Gets a JPD given its id

Since: 4.0
Notes: Requires Artifactory Enterprise

Security: Requires an admin user
Usage: GET request to /mc/api/v1/jpds/{id}

Consumes: application/json

Return codes:
200 - Success

Example:


Sample usage:

GET /api/v1/jpds/JPD-1

{
  "id": "JPD-1",
  "licenses": [
      {
          "expired": false,
          "license_hash": "2c2ef96d8a90ea2bb91287258dc8ab72a6b0f749",
          "licensed_to": "jfrog.com",
          "type": "ENTERPRISE_PLUS_TRIAL",
          "valid_through": "2020-02-14"
      }
  ],
  "location": {
      "city_name": "Nuuk",
      "country_code": "GL",
      "latitude": 64.18347,
      "longitude": -51.72157
  },
  "name": "HOME",
  "services": [
      {
          "status": {
              "code": "ONLINE"
          },
          "type": "ARTIFACTORY"
      },
      {
          "status": {
              "code": "ONLINE"
          },
          "type": "JFMC"
      }
  ],
  "status": {
      "code": "ONLINE",
      "message": "All services are online",
      "warnings": []
  },
  "tags": [],
  "url": "http://jpd.local/"
}



Delete JPD

Description: Removes a JPD from Mission Control

Since: 4.0
Notes: Requires Artifactory Enterprise
Security: Requires an admin user
Usage: DELETE /mc/api/v1/jpds/{id}
Return codes:

200 - Success
204 - No content
404 - Not found

Sample usage:

DELETE /api/v1/jpds/JPD-321

ACCESS FEDERATION

Get Access Federation Configuration for a Single JPD

Description: Gets the Access Federation configuration for a specific JPD. Returns the Federation targets configured for the provided JPD.

Since: 4.0
Notes: 

  • Requires Artifactory Enterprise+
  • Overwrites manual configuration of Access Federation in access config files.

Security: Requires an admin user

Usage: GET /mc/api/v1/federation/{JPD ID}
Return codes:

200 - Success
400 - The JPD is not a valid Access Federation candidate.
404 - The JPD was not found.
Consumes: application/json

Sample usage:

GET /api/v1/mc/api/v1/federation/JPD-1

{
    "entities": [
        "GROUPS",
        "USERS"
    ],
    "targets": [
        {
            "name": "JFP-2",
            "code": "access2JPDId",
            "url": "http://localhost:37837/access"
        }
    ]
}



Get Access Federation Configuration for All JPDs 

Description: Gets the Access Federation configurations for all the JPDs.

Since: 4.0
Notes: Requires Artifactory Enterprise+
Security: Requires an admin user

Usage: GET /mc/api/v1/federation?includeNonConfiguredJPDs=false
Return codes:

200 - Success

Produces: application/json


Sample usage:

GET /api/v1/mc/api/v1/federation?include_non_configured=false
[
  {
    "source": "artifactory1",
    "entities": [
      "GROUPS",
      "USERS"
    ],
    "targets": [
      {
        "name": "JPD-2",
        "code": "access2JPDId",
        "url": "url2"
      }
    ]
  }
]


Configure Access Federation on a JPD

Description: Configures Access Federation for a specific JPD. As a pre-requisite, the source and targets must have been configured properly for Access Federation based on this
Since: 4.0
Notes: Requires Artifactory Enterprise+
Security: Requires an admin user
Usage: PUT /mc/api/v1/federation/{JPD ID}

Return codes:
200 - Success
400, 422 - Invalid input
404 - JPD not found or not an Artifactory


Sample usage:

PUT /api/v1/federation/
{
  "entities": [
    "USERS",
    "GROUPS"
  ],
  "targets": [
    {
      "name": "artifactory2",
      "url": "http://localhost:8080/access"
    }
  ]
}

Sample response:

[
  {
    "label": "Get configuration of artifactory1",
    "status": "OK"
  },
  {
    "label": "Get Access token from artifactory1",
    "status": "OK"
  },
  {
    "label": "Check if artifactory2 trusts artifactory1",
    "status": "OK"
  },
  {
    "label": "Send configuration to artifactory1",
    "status": "OK"
  },
  {
    "label": "Add target artifactory2 to artifactory1",
    "status": "OK"
  }
]

Get Access Federation Candidates

Description: Gets the Access Federation candidates.
Since: 4.0
Notes: Requires Artifactory Enterprise+
Security: Requires an admin user
Usage: GET /mc/api/v1/federation/candidates
Return codes:
200 - Success

Sample usage:

GET /api/v1/mc/api/v1/federation/candidates



Create Mesh

Description: Creates a mesh topology. As a pre-requisite, the source and targets must have been configured properly for Access Federation based on this

Since: 4.0
Notes: Requires Artifactory Enterprise+
Security: Requires an admin user
Usage: POST /mc/api/v1/federation/create_mesh
Return codes:

200 - Success
400, 422 - Invalid input
404 - JPD not found or not an Artifactory

Request Example:

POST /api/v1/federation/create_mesh
{
  "jpd_ids": [
    "JPD-12",
    "JPD-13"
  ],
  "entities": [
    "USERS",
    "GROUPS",
    "PERMISSIONS",
    "TOKENS"
  ]
}

Response Example:

[ {
  "label" : "SUCCESSFUL",
  "status" : "OK"
} ]


SUPPORT

Create Support Bundle

Description: Create a new support bundle.
Since: 4.0
Security: Requires an admin user
Notes: All bundle items are optional.
Usage: POST /mc/api/v1/system/support/bundle

Return codes:
202 - Support bundle is being created and will be available soon
400 - Invalid option values
403 - Unauthorized

Sample usage:

POST /api/v1/system/support/bundle
{
  "name": "JFMC support bundle",
  "description": "Support bundle generated because of issue with XYZ",
  "parameters": {
    "configuration": true,
    "system": true,
    "thread_dump": {
      "count": 1,
      "interval": 0
    },
    "logs": {
      "include": true,
      "start_date": "2018-12-25",
      "end_date": "2019-01-07"
    }
  }
}

Example Output:

HTTP/1.1 202 Accepted
Content-Type: application/json
Server: mission-control/SNAPSHOT
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Length: 247
{
   "id" : "SUPP20180912154413548991",
   "artifactory" : {
	   "service_id" : "jfrt@4754684682741",
	   "bundle_url" : "http://artifactory.jfrog.com/artifactory/jfrog-support-bundle/SUPP20180912154413548991/jfmc/test_JPD
   }
}

Get Support Bundles List

Description: Get the list of available support bundles.
Since: 4.0
Security: Requires an admin user
Usage: GET /mc/api/v1/system/support/bundles

Return codes:
200 - Successful
403 - Unauthorized


Sample usage:

GET /mc/api/v1/system/support/bundles
{
  "count" : 2,
  "bundles" : [ {
    "name" : "A",
    "description" : "aaa",
    "id" : "1",
    "created" : "2018-10-01T09:50:11Z"
}, {
   "name" : "B",
   "id" : "2",
   "created" : "2018-10-01T09:50:11Z"
  } ]
}



Get Details of a Support Bundle 

Description: Gets the details of a specific support bundle.
Since: 4.0
Security: Requires an admin user
Usage: GET /mc/api/v1/system/support/bundle/{id}

Return codes:
200 - Successful
403 - Unauthorized
404 - Supplied ID does not refer to an existing support bundle


Sample usage:


GET /mc/api/v1/system/support/bundle/SUPP20180912154413548991 
{
  "name" : "issue #1234",
  "description" : "Support bundle created for issue #1234 investigation",
  "artifactory" : {
     "service_id" : "jfrt@4754684682741",
     "bundle_url" : "http://artifactory.jfrog.com/artifactory/jfrog-admin-supportbundle/SUPP20180912154413548991/jfmc/01c7b8rg70nrqr1cck7k4x0yp7"
   },
   "parameters" : {
     "configuration" : true,
     "system" : true,
     "logs" : {
        "include" : true,
        "start_date" : "2018-09-30",
        "end_date" : "2018-10-01"
   },
     "thread_dump" : {
       "count" : 1,
       "interval" : 0
   }
 
  },
  "available" : 5,
  "created" : "2018-10-01T09:50:10Z"
}



Download Support Bundle 

Description: Downloads a support bundle as a ZIP file.
Since: 4.0
Security: Requires an admin user. You need to have the "Download folder" permission enabled on Artifactory.
Usage: GET /mc/api/v1/system/support/bundle/{id}/archive

Return codes:
200 - Successful
403 - Unauthorized (it may be that the "Download folder" option is not enabled on the Authentication Provider Artifactory)
404 - Supplied ID does not refer to an existing support bundle or the ZIP cannot be found in the Authentication Provider Artifactory repository

Sample usage:

GET /mc/api/v1/system/support/bundle/SUPP20180912154413548991/archive



Delete Support Bundle 

Description: Deletes a support bundle, along with the ZIP file in Artifactory.
Since: 4.0
Security: Requires an admin user
Usage: DELETE /mc/api/v1/system/support/bundle/{id}

Return codes:
204 - Successful
403 - Unauthorized
404 - Supplied ID does not refer to an existing support bundle

Sample usage:


DELETE /mc/api/v1/system/support/bundle/SUPP20180912154413548991


LICENSE BUCKETS



Get Buckets


Description: Retrieves all the license buckets in the system.
Since: 4.0
Notes: Requires Artifactory Enterprise
Security: Requires an admin user
Usage: GET /mc/api/v1/buckets

Return codes:

200 - Success
Produces: application/json
Sample Response:


[
	{
		"identifier" : "<bucket id>",
  		"name" : "<bucket name>",
  		"size" : <number of licenses in bucket>,
  		"license_type": "<ENTERPRISE | EDGE>"
	}
]

Sample Usage:

GET /mc/api/v1/buckets
 
[
{
  "id" : "12345",
  "name" : "bucket-test-1",
  "size" : 10,
  "license_type": "ENTERPRISE" 
},
{
  "id" : "1234567",
  "name": "bucket-test-2",
  "size" : 5,
  "license_type": "EDGE" 
}
]




Create Bucket 


Description: Creates a new License Bucket.
Since: 4.0
Notes: Requires Artifactory Enterprise
Security: Requires an admin user
Usage: POST /mc/api/v1/buckets

Return codes:

201 - Created
409 - Name '<Bucket name>' already exists
409 - Url '<Bucket URL>' already exists

Consumes: application/json

Sample usage:


POST /api/v1/buckets
{
  "name" : "main-bucket",
  "url" : "https://bintray.jfrog.com/license-buckets/test_jfrog.com/12345678/12345678.json?expiry=1528199600307&id=ABCDEFGhiJkLmNoPQR",
  "key" : "16629dbf7fefc9d179b36ba005685c2dd8376aad3278178e735da1633c6bd3c6"
}


Sample response:


{
  "subject" : "JFrog",
  "product_name" : "Artifactory",
  "product_id" : 6,
  "license_type" : "HA",
  "issued_date" : "2018-04-12T16:02:55.549+03:00",
  "valid_date" : "2019-04-12T16:02:54.759+03:00",
  "quantity" : 10,
  "signature" : "06307c34405e6ab70c5d249a7ba7cffd81947d5f",
  "name" : "main-bucket",
  "used" : 0,
  "url" : "https://bintray.jfrog.com/license-buckets/test_jfrog.com/12345678/12345678.json?expiry=1528199600307&id=ABCDEFGhiJkLmNoPQR"
}

Upload Bucket

Description: Uploads and creates a new License Bucket.
Since: 4.0
Notes: Requires Artifactory Enterprise
Security: Requires an admin user
Usage: POST /mc/api/v1/buckets
Content-Type: multipart/form-data

Return codes:
201 - Created
400 - Your bucket file could not be used. Please verify that the file is correct and that the key is valid.
409 - Name '<Bucket name>' already exists

Consumes: application/json

name | Bucket’s name in Mission Control
file | Path to the bucket file
key  | Key used to decrypt the bucket

Produces: application/json

Sample usage:

curl -X POST 'http://localhost:8082/mc/api/v1/buckets' -H 'Authorization: Bearer <token>' -H 'Content-Type: multipart/form-data' -F 'file=@/tmp/728939433.json;type=application/octet-stream' -F 'key=d18fc5bc05dc3b6419ab6cd127f16cf6b57d7650ea0ef03cde130918f6f25487' -F 'name=mybucket'

Sample response:

{
  "subject" : "JFrog",
  "product_name" : "Artifactory",
  "product_id" : 6,
  "license_type" : "HA",
  "issued_date" : "2016-04-12T16:02:55.549+03:00",
  "valid_date" : "2017-04-12T16:02:54.759+03:00",
  "quantity" : 10,
  "identifier" : "bucket-test-1",
  "signature" : "06307c34405e6ab70c5d249a7ba7cffd81947d5f",
  "name" : "Test-bucket-name",
  "used" : 0
}

Delete Bucket

Description: Deletes a bucket.
Since: 4.0
Notes: Requires Artifactory Enterprise
Security: Requires an admin user 
Usage: DELETE /mc/api/v1/buckets/{name} 
Return codes: 204 - Success 

Sample usage:


DELETE /api/v1/buckets/main-bucket
 
204 No Content

Get Bucket Status

Description: Get the report for a specified bucket.
Since: 4.0
Notes: Requires Artifactory Enterprise
Security: Requires an admin user
Usage: GET /api/v1/buckets/{identifier}/report
Produces: application/json

Response format:

{
  "identifier": "<bucket ID>",
  "name": "<bucket name>",
  "size": "<total number of licenses in bucket>",
  "valid_through": "<valid through date>",
  "issued": "<issue date>",
  "type": "<license type>",
  "licenses": {
    "used": "<Number of licenses that are in use>",
    "available": "<Number of licenses that are in available>",
    "max_used": "<The maximum number of licenses ever used concurrently>"
  },
  "jpds": [
    {
      "name": "<JPD name>",
      "license_count": "<Number of licenses used by this JPD>"
    }
  ],
  "split_buckets": [
    {
      "name": "<Split bucket name>",
      "identifier": "<Split bucket identifier>",
      "issued": "<Issue date>",
      "license_count": "<Number of licenses>"
    }
  ],
  "unknown_uses": [
    {
      "name": "<Free label of an unknown usage>",
      "license_count": "<Number of licenses used>"
    }
  ],
  "pipelines": {
    "execution_nodes": "<Number of execution nodes for pipelines>"
  }
}

Return codes:

200 - Success

Sample usage:


example output
GET /api/v1/buckets/415921223/report
{
    "identifier": "266200796",
    "name": "edge-bucket",
    "size": 10,
    "valid_through": "2020-02-14T00:00:00.000Z",
    "issued": "2019-02-14T14:27:29.584Z",
    "type": "EDGE_TRIAL",
    "licenses": {
        "used": 0,
        "available": 10,
        "max_used": 0
    }
}



Attach License 


Description: Attaches a license from a bucket to the specified JPD. 
Since: 4.0
Notes: Requires Artifactory Enterprise. For applying licenses to Artifactory Pro, use the Artifactory API.
Security: Requires an admin user
Usage: POST /mc/api/v1/buckets/{name}/deploy
Consumes: application/json


{
    "jpd_id" : "<a JPD id>",
    "license_count" : <number of licenses to upload to Artifactory> 
} 

Produces: application/json
Return codes:

200 - Success

400 - "JPD with id <jpd_id> was not found."

500 - "Cannot deploy licenses from bucket <bucket_name> to <jpd_id>"

Sample usage:


attachlicense.json
POST /api/v1/buckets/mybucket/deploy
{
    "jpd_id" : "JPD-12",
    "license_count" : 1
} 


Sample response:


example output
{
  "success" : true,
  "message" : "Assigned 1 license from bucket bucket-test-1 to JPD-12."
}


Acquire License

Description: Acquires one or several license(s) from a bucket and returns it or them. Those licenses are marked as used in the bucket report under the "Unknown usage" section.
Since: 4.0
Notes: Requires Artifactory Enterprise
Security: Requires an admin user
Usage: POST /mc/api/v1/buckets/{name}/acquire
Consumes: application/json

{
    "name" : "<a free text label>",
    "license_count" : <number of licenses to acquire> 
} 

Produces: application/json
Return codes:

200 - Success

404 - "The entity 'LicenseBucket' with identifier '<Non existing Bucket Id>' was not found."

Sample usage:

acquirelicense.json
POST /api/v1/buckets/mybucket/acquire
{
    "name" : "team-A-license",
    "license_count" : 1
} 


Sample response:


example output
{
  "license_keys" : [ "<license-key>" ]
}


Release License

Description: Releases a license from a bucket given the JPD id or label previously used by an "acquire" call.
Since: 4.0
Notes: Requires Artifactory Enterprise
Security: Requires an admin user
Usage: POST /mc/api/v1/buckets/{name}/release
Consumes: application/json

{
    "name" : "<a JPD id or a free text label>"
} 

Produces: application/json
Return codes:

204 - No Content
404 - "The entity 'LicenseBucket' with identifier '<Non existing Bucket Id>' was not found."
409 - "The Jpd must be offline before you can detach its license"
409 - "No licenses to release for bucket: <bucket id>, instance name: <jpd id or free text label>"

Sample usage:

acquirelicense.json
POST /api/v1/buckets/mybucket/release
{
    "name" : "team-A-license"
} 



  • No labels
Copyright © 2023 JFrog Ltd.